Why mongoose $pull does not remove item from an array - node.js

const userSchema = new mongoose.Schema({
name: String,
products: []
});
eg. User:
{ name: 'Steve', products: ['111a', '222b']}
I want to remove the product of given name from the user of given ID.
User.findByIdAndUpdate(userId, { $pull: { products: req.body.prodId } }, (err, user) => {
if (err) { res.send('error_3853852'); return; }
res.send('updated'); return;
})
As a result it is not removed and no error occured

Related

How to insert new data in a object array in mongoose?

I am trying to insert a new data in a specific array of that server, since new data will be added while the user speaks in several servers. I mean, if the user receives a warn, it is stored in the array of the server in which the command is executed and not in another server, and vice versa and it is carried out in another server
warnSet = await User.findOne(
{
_id: user.id,
"warns._id": message.guild.id,
},
(err, usuario) => {
if (err) console.error(err);
if (!usuario) {
const newUser = new User({
_id: user.id,
userName: user.username,
warns: [
{
_id: message.guild.id,
warn: 1,
},
],
});
newUser.save().catch((err) => console.error(err));
return;
} else {
usuario
.updateOne(
{ "warns._id": message.guild.id },
{
$set: {
"warns.warn": 2,
},
}
)
.catch((err) => console.error(err));
return;
}
}
);
The Model:
const mongoose = require("mongoose");
const userSchema = mongoose.Schema({
_id: Number,
userName: String,
warns: [
{
_id: Number,
warn: Number,
},
],
});
module.exports = mongoose.model("User", userSchema, "user");

MongoDB array of objects update

I'm trying to update array of user information objects in mongoose.
I've stored the user core information in the login process, I want to update some of user information when user tries to make an order.
Here is the code for the model
const mongoose = require('mongoose');
const { ObjectId } = mongoose.Schema;
const userSchema = new mongoose.Schema(
{
name: String,
email: {
type: String,
required: true,
index: true,
},
role: {
type: String,
default: 'subscriber',
},
info: [
{ country: String },
{ city: String },
{ address: String },
{ phone: String },
{ birthdate: Date },
{ gender: { type: String, enum: ['Male', 'Female'] } },
],
// wishlist: [{ type: ObjectId, ref: "Product" }],
},
{ timestamps: true }
);
module.exports = mongoose.model('User', userSchema);
In my controller I'm getting the data from front-end react app as JSON format, I want to push some data to info which is an array of objects in the users model above.
exports.createOrder = async (req, res) => {
// Here I constract the data
const { plan, service, fullName, country, city, address } = req.body.order;
const { user_id } = req.body;
// This the method I tried
try {
const user = await User.updateOne(
{
_id: user_id,
},
{
$set: {
'info.$.country': country,
'info.$.city': city,
'info.$.address': address,
},
},
{ new: true }
);
if (user) {
console.log('USER UPDATED', user);
res.json(user);
} else {
res.json((err) => {
console.log(err);
});
}
const newOrder = await new Order({
orderPlan: plan,
orderService: service,
orderUser: user_id,
}).save();
console.log(newOrder);
console.log(req.body);
} catch (error) {
console.log(error);
}
};
I tired other solutions like
const user = await User.updateOne(
{
_id: user_id,
info: { $elemMatch: { country, city, address } },
},
{ new: true }
);
So do I need to reformat my model or there is a way to update this array of objects?
Option 1
Use $[]
db.collection.update(
{},
{ $set: { "info.$[i].country": "a1" }} ,
{ arrayFilters: [ { "i.country": "a" } ] }
)
Demo - https://mongoplayground.net/p/UMxdpyiKpa9
Option 2
if you know the index
Demo - https://mongoplayground.net/p/41S7qs6cYPT
db.collection.update({},
{
$set: {
"info.0.country": "a1",
"info.1.city": "b1",
"info.2.address": "c1",
"info.3.phone": "d1"
}
})
Suggestions -
Change info schema to object instead of an array

mongodb won't delete an element from ObjectId array

My schema looks like the following:
const userSchema = new Schema({
...
followings: [
{
user:{
type: Schema.ObjectId,
ref: 'User'
},
}
],
followers: [
{
user:{
type: Schema.ObjectId,
ref: 'User'
},
}
],
}, {timestamps: true})
And I need to implement "unfollow" feature.
I am currently trying this:
try {
// check if your id doesn't match the id of the user you want to unfollow
if (user._id === current_id) {
return res.status(400).json({ error: 'You cannot unfollow yourself' })
}
// remove the id of the user you want to unfollow from following array
const query = {
_id: current_id
}
const update = {
$pull: { "followings": {"_id": user._id }}
}
const updated = User.update(query, update)
// remove your id from the followers array of the user you want to unfollow
const secondQuery = {
_id: user._id
}
const secondUpdate = {
$pull: { "followers": {"_id": current_id} }
}
const secondUpdated = User.update(secondQuery, secondUpdate)
if (!updated || !secondUpdated) {
return res.status(404).json({ error: 'Unable to unfollow that user' })
}
res.status(200).json({
update,
secondUpdate
})
}
catch (err) {
res.status(400).send({ error: err.message })
}
This gives status 200 and sends update & secondUpdate to the client,
but the actual object doesn't get deleted from the database.
What is wrong with my code?
If you are using mongodb native drive
You should import mongodb ObjectID. Before performing operations.
const ObjectId = require('mongodb').ObjectID;
$pull: { "followers": {"_id": current_id} }
change to:
$pull: { "followers": {"_id": new ObjectId(current_id) }
Thank you for your answers.
In my case, the following worked for me.
try {
// check if your id doesn't match the id of the user you want to unfollow
if (user._id === current_id) {
return res.status(400).json({ error: 'You cannot unfollow yourself' })
}
// remove the id of the user you want to unfollow from following array
const query = {
_id: current_id
}
const update = {
$pull: { followings: {_id: user._id }}
}
const updated = User.updateOne(query, update, {
safe: true
}, function(err, obj) {
console.log(err);
})
// remove your id from the followers array of the user you want to unfollow
const secondQuery = {
_id: user._id
}
const secondUpdate = {
$pull: { followers: {_id: current_id} }
}
console.log(secondQuery)
console.log(secondUpdate)
User.updateOne(secondQuery, secondUpdate, {
safe: true
}, function(err, obj) {
res.status(200).json({
obj
});
})
}
catch (err) {
res.status(400).json({ error: err.message })
}

Mongoose update nested array

In the schema, I have an object defender.placements.cruisers: []
i try to insert obj to it but it insert only status, direction, size but empty grids then i try to update again it remove the old data (status, direction, size) and insert new data
//My Model
import mongoose from 'mongoose';
const Schema = mongoose.Schema;
export const CoordinateSchema = new Schema({row: Number, col: Number});
export const ShipSchema = new Schema({
grids: [CoordinateSchema],
status: String,
direction: String,
size: Number
});
export const GameStateSchema = new Schema({
gameState: {
type: String,
required: 'state status',
default: 'joining'
},
attacker: {
hitGrids: [CoordinateSchema],
missGrids: [CoordinateSchema]
},
defender: {
placements: {
battleships: [ShipSchema],
cruisers: [ShipSchema],
destroyers: [ShipSchema],
submarines: [ShipSchema]
}
},
occupyGrids: [CoordinateSchema],
adjacentGrids: [CoordinateSchema],
size: {
type: String,
default: '10'
}
});
export default mongoose.model('GameState', GameStateSchema);
below, the code that i try to push data to array in
await GameState.update({
_id: testId
},{
$set: {
'defender.placements': {
[shipType]: {
status: utils.shipStatus.float,
direction: shipDirection,
size: coordinates.length,
$addToSet: {
grids: coordinates
}
}
}
},
$addToSet: {
occupyGrids: coordinates,
adjacentGrids: closeGrids
}
}, (err, gm) => {
if (err) {
return res.send(err);
}
});
here is my result that i got but
it works
const newPlacements = [{
grids: [...coordinates],
status: utils.shipStatus.float,
direction: shipDirection,
size: coordinates.length
}];
const keyPlacements = `defender.placements.${shipType}`;
await GameState.update({
_id: testId
},{
$addToSet: {
[keyPlacements]: newPlacements,
occupyGrids: coordinates,
adjacentGrids: closeGrids
}
}, (err, gm) => {
if (err) {
return res.send(err);
}
});

Populate in Mongoose not working

I am trying to perform associations by referencing method. There are 2 models:
1. User
2. Product
I have established one-to-one relationship of 1 user can have multiple products. User creation is successful
Product creation is successful
Code Inputs
var mongoose = require("mongoose");
mongoose.connect("mongodb://localhost/product_demo_x9");
Product Schema
var productSchema = new mongoose.Schema({
category : String,
Brand: String
});
var Product = mongoose.model("product", productSchema);
User Schema
var userSchema = new mongoose.Schema({
email: String,
name: String,
products: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Product"
}
]
});`
var User = mongoose.model("user", userSchema);
User Creation
User.create({
email: "madhur#google.com",
name: "Maddy"
},function(err,newUser){
if(err){
console.log(err);
}
else {
console.log(newUser);
}
});
Product Creation
Product.create({
category: "Smartwatches",
Brand: "Samsung and Google"
},
function(err,product){
console.log(product);
User.findOne({name : "Maddy"},function(err,foundUser){
if(err) {
console.log(err);
}
else {
foundUser.products.push(product);
foundUser.save(function(err,updatedUser){
if(err){
console.log(err);
}
else {
console.log(updatedUser);
}
});
}
});
});
Display of associated Data on the console
User.find({email: "madhur#google.com"}).
populate("products").
exec(function(err,user){
if(err){
console.log(err);
}
else {
console.log(user);
}
});
Code Outputs
User Creation (Success)
[{
products: [],
_id: 5a47acb0317d4e3c2081b8ce,
email: 'madhur#google.com',
name: 'Maddy',
__v: 0
}]
Product Creation and associating (Success)
{
_id: 5a47acd53c771123b4018ff1,
category: 'Smartwatches_2',
Brand: 'Samsung and Google',
__v: 0
}
{
products: [ 5a47acd53c771123b4018ff1 ],
_id: 5a47acb0317d4e3c2081b8ce,
email: 'madhur#google.com',
name: 'Maddy',
__v: 1
}
Display of embedded data using populate - Failure!!
{ MissingSchemaError: Schema hasn't been registered for model "products".
Use mongoose.model(name, schema)
at new MissingSchemaError
Can anyone please explain me how to do it correctly?
Thanks in Advance
Model Name is Case-sensitive
'Product' is not equal to 'product'
and when u create a model as 'product' (singular) it converts it into plural, i.e. 'products', this is default mongoose behavior, can be overridden.
so change the following:
var userSchema = new mongoose.Schema({
email: String,
name: String,
products: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "products" //<---- changed 'Product' to 'products'
}
]
});`
var User = mongoose.model("user", userSchema);
Try this
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/product_demo_x9');
var productSchema = new mongoose.Schema({
category: String,
Brand: String
});
var Product = mongoose.model('Product', productSchema);
var userSchema = new mongoose.Schema({
email: String,
name: String,
products: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Product'
}
]
});
var User = mongoose.model('User', userSchema);
User.create({
email: 'madhur#google.com',
name: 'Maddy'
}, function(err, newUser) {
if (err) {
console.log(err);
} else {
console.log(newUser);
}
});
Product.create({
category: 'Smartwatches',
Brand: 'Samsung and Google'
},
function(err, product) {
console.log(product);
User.findOne({name: 'Maddy'}, function(err, foundUser) {
if (err) {
console.log(err);
} else {
foundUser.products.push(product);
foundUser.save(function(err, updatedUser) {
if (err) {
console.log(err);
} else {
console.log(updatedUser);
}
});
}
});
});
User.find({email: 'madhur#google.com'})
.populate('products')
.exec(function(err, user) {
if (err) {
console.log(err);
} else {
console.log(user);
}
});
Solved
Did the following
Downgraded my Mongoose version from 5.00x to 4.10.8 using the following command npm remove mongoose then npm install mongoose#4.10.8 --save
Made the following change in app.js file
var userSchema = new mongoose.Schema({
email: String,
name: String,
products: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "product" //<---- changed 'Product' to 'product'
}
]
});`
var User = mongoose.model("user", userSchema);
Thanks to the Stack community for giving a try!

Resources