MongoError: The positional operator did not find the match needed from the query. at Function.create() - node.js

I am trying to update values into an object array(users) if it does not already exist in MongoDB. Here is my Schema:
ownerid:{
type: Number,
required: 'This field is required'
},
name:{
type: String
},
capacity:{
type: Number
},
basePrice:{
type: Number
},
users:[{
id: Number,
price: Number,
target: Number,
frequency: Number
}],
filePath:{
type: String
},
status:{
type: String
}
});
The following is my router method:
app.post('/userBid',urlEncodedParser,function(req,res){
resName=req.body.resName;
console.log(resName);
Resource.find({"name":resName},{"users.id": userid},function(err,existingUser){
if (!existingUser){
console.log("already in queue");
//res.render('userHome.ejs');
}
else{
console.log("in update");
Resource.update({'name': resName},
{'$set': {
'users.$.frequency': 1,
'users.$.id': userid,
'users.$.price': req.body.price,
'users.$.target': req.body.target
}},{'multi': true},
function(err,model) {
if(err){
console.log(err);
return res.send(err);
}
return res.json(model);
});
}
});
});
I have tried using $push but that does not seem to work either. Also I can't use '0' instead of '$' as multiple users will be inserted by the users and I need to store them all.

Issue :
Reason why we use $ is to update a specific object/few specific objects in an array field that meet our condition. So when you use any positional operators like $ or $[] then in filter part of .update({filterPart},{updatePart}) query you need to use a filter to find specific object in array. So for example if id field is unique in users array then you can use it to filter/find the object needs to be updated.
Try this below code :
app.post("/userBid", urlEncodedParser, function (req, res) {
resName = req.body.resName;
console.log(resName);
/** Use findOne if `name` is unique.
* Cause `existingUser` will be array, instead findOne will return an object or null - So you can just do if(existingUser)to check true values */
Resource.find({ name: resName }, { "users.id": userid }, function (
err,
existingUser
) {
if (!existingUser) {
console.log("already in queue");
//res.render('userHome.ejs');
} else {
console.log("in update");
Resource.update(
{ name: resName, "users.id": userid }, /** `"users.id": userid` is the only change needed */
{
$set: {
"users.$.frequency": 1,
"users.$.id": userid,
"users.$.price": req.body.price,
"users.$.target": req.body.target,
},
},
{ multi: true },
function (err, model) {
if (err) {
console.log(err);
return res.send(err);
}
return res.json(model);
}
);
}
});
});

Related

Mongoose reports no error on updating, but does not update

losing my mind here for something for a MongoDB document update with Mongoose, not reporting any error but not actually updating successfully.
I have this schema:
/**
* Branch Schema
*/
let BranchSchema = new Schema({
name: String,
domain: String,
email: String,
bm: { type: Schema.ObjectId, ref: 'User' },
st: [{ type: Schema.ObjectId, ref: 'User' }],
stockCurrent: {
paper: Schema.Types.Object,
ink: Schema.Types.Object
},
stockNeeded: {
paper: Schema.Types.Object,
ink: Schema.Types.Object
},
}, { versionKey: false, usePushEach: true });
mongoose.model('Branch', BranchSchema);
Trying to update stockCurrent, using this logic:
Branch.findById(config.branch.id, function (err, branch) {
if (err) {
res.status(422).send({
message: 'הסניף לא נמצא'
});
} else {
console.log(branch);
Object.keys(req.body.stock).forEach(function (type) {
Object.keys(req.body.stock[type]).forEach(function (code) {
if (req.body.stock[type][code] > 0) {
if (typeof branch.stockCurrent[type][code] === 'undefined') {
branch.stockCurrent[type][code] = 0;
}
branch.stockCurrent[type][code] += req.body.stock[type][code];
}
});
});
console.log(branch);
branch.save(function (err, updated) {
console.log("err: " + err);
if (err) {
stock.remove();
res.status(422).send({
message: 'שגיאה בשמירת מלאי'
});
} else {
console.log(updated);
res.send({
message: 'מלאי נוסף בהצלחה'
});
}
});
}
});
I get to to success part, having my console log this:
{
"_id":5dd276a6bcc29a13789fcecb,
"name":"בצלאל ארכיטקטורה",
"domain":"bezalel.eazix.io",
"email":"eazix.1.bezalel#gmail.com",
"bm":5cdd2130d192ea03a87d2dfd,
"stockNeeded":{
"ink":{
"GY":2,
"PM":2,
"M":2,
"MBK":2,
"PBK":2,
"PC":2,
"Y":2,
"C":2,
"waste":2
},
"paper":{
"COATED":5,
"PLAIN":5,
"PHOTO":3
}
},
"stockCurrent":{
"paper":{
"PLAIN":0
},
"ink":{
"waste":0
}
},
"st":[
]
}{
"_id":5dd276a6bcc29a13789fcecb,
"name":"בצלאל ארכיטקטורה",
"domain":"bezalel.eazix.io",
"email":"eazix.1.bezalel#gmail.com",
"bm":5cdd2130d192ea03a87d2dfd,
"stockNeeded":{
"ink":{
"GY":2,
"PM":2,
"M":2,
"MBK":2,
"PBK":2,
"PC":2,
"Y":2,
"C":2,
"waste":2
},
"paper":{
"COATED":5,
"PLAIN":5,
"PHOTO":3
}
},
"stockCurrent":{
"paper":{
"COATED":1,
"PHOTO":2,
"PLAIN":0
},
"ink":{
"PM":1,
"waste":0
}
},
"st":[
]
}**"err":null**{
"_id":5dd276a6bcc29a13789fcecb,
"name":"בצלאל ארכיטקטורה",
"domain":"bezalel.eazix.io",
"email":"eazix.1.bezalel#gmail.com",
"bm":5cdd2130d192ea03a87d2dfd,
"stockNeeded":{
"ink":{
"GY":2,
"PM":2,
"M":2,
"MBK":2,
"PBK":2,
"PC":2,
"Y":2,
"C":2,
"waste":2
},
"paper":{
"COATED":5,
"PLAIN":5,
"PHOTO":3
}
},
"stockCurrent":{
"paper":{
"COATED":1,
"PHOTO":2,
"PLAIN":0
},
"ink":{
"PM":1,
"waste":0
}
},
"st":[
]
}
I can see the here the initial state, the updated version before saving, and the the err:null, and the allegedly updated document.
but alas! the document wasn't really updated. it remains the same.
I have tried many things, searching and looking for similar cases, checking my schema, adding useStrict:false to the schema, nothing helps.
Mongoose ver 4.13.20, Mongodb ver 3.6.17
SOS
Dor
I'm guessing the SchemaTypes are the problem? In Mongoose 4.x, these are the only valid SchemaTypes:
String
Number
Date
Buffer
Boolean
Mixed
Objectid
Array
Notice that Mixed is an option but not Object. You need to tell Mongoose that you updated a Mixed field using model.markModified('pathName'). See the Mixed docs.
So in your case, the code below may fix the issue:
branch.markModified('stockCurrent');
branch.save(function (err, updated) {
// ...

Appending array of ObjectIds

I have an array of ObjectIds in a collection and I want to simply add the ObjectId of another collection.
router.post('/add/child', (req, res) => {
console.log(req.body);
switch (req.body.type) {
case "category":
Category.findOne({_id: req.body.to})
.then(category => {
if (!category) {
res.json({error: req.body.type + " not found"});
}
category.update({$push: {words: req.body.child}});
console.log('category', category);
res.json({category});
})
.catch(err => {
console.log(err);
res.json(err.response)
})
default:
break;
}
}
req.body is:
{ type: 'category',
to: '5c312fd6ec0fff1c280aca19',
child: '5c323bed9b0f713aa0d49399' }
category is:
category { words: [],
_id: 5c312fd6ec0fff1c280aca19,
title: 'Weather',
[__v: 0 }
The model for category:
category: {
title: {
type: String,
required: true
},
variation: {
type: String
},
words: [{
type: Schema.Types.ObjectId,
ref: "words"
}]
},
To append the array, you need the $push operator within an update method like findOneAndUpdate or findByIdAndUpdate. If you are using your existing method, you need to call the push method on the array itself and then save i.e.:
Category.findById(req.body.to).then(category => {
if (!category) {
res.json({error: req.body.type + " not found"});
}
category.words.push(req.body.child);
return category.save();
}).then(updatedCategory => {
console.log('updatedCategory', updatedCategory);
res.json({ category: updatedCategory });
})
A better way which is atomic would be to use the findOneAndUpdate method like:
Category.findByIdAndUpdate(req.body.to,
{'$push': {'words': req.body.child}},
{new: true},
)
.exec()
.then(category => {
console.log('category', category);
if (!category) {
res.json({error: req.body.type + " not found"});
}
res.json({ category });
})
.catch(err => {
console.log(err);
res.json(err.response)
})
I am not so clear about what you are looking for. But, I believe you are trying to fetch results from two collections. $lookup is the best way to do so. You can customize your result using $project.
db.category.aggregate([
{
$lookup:
{
from: "words",
localField: "id_of_words",
foreignField: "id_of_category", // Id of category & words should match.
as: "docs"
}
}
])

update array of object of object MongoDB

I have this model
student: {
package:{
type: mongoose.Schema.Types.ObjectId,
ref: 'Package',
},
history: [
{
package: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Package',
},
orderDate: {
type: Date,
default: new Date().toLocaleDateString('id'),
},
Status: {
type: String,
default: 'Pending',
},
},
],
}
What I want to do is that I want to update Student.package and Student.history in 1 pass
I create this method in my model
StudentSchema.methods.updatePackage= function(idPackage) {
this.package = idPackage;
return this.save();
};
StudentSchema.methods.updateHistory= function(idPackage) {
this.history.push(idPackage);
return this.save();
};
and I'm trying to do something like this in my controller
buyPack: async (req, res, next) => {
try {
let dataStudent = await Student.findById('5b83443040e3751bb4e32a21');
await dataStudent.updatePackage(req.body);
await dataStudent.updateHistory(req.body);
return res.json(dataStudent);
} catch (err) {
console.log(err);
next(err);
}
},
I think the first and second methods are wrong, but I have tried to figure it out in almost half of day, but still no luck. What is the best way to achieve my goals?
Do I make my model wrong? or do the methods I created are wrong?
Mongoose model rename with plural .. and you refer with singular with "S", "Package" change it to "Packages"

Mongo Find is not working

This is my user schema
var UserSchema = new Schema({
Pcard: [{ type: Schema.Types.ObjectId, ref: 'Pcard' }]
})
These are id's saved in user Pcard array
"user": { // id 59560bc83e1fdc2cb8e73236
"Pcard": [
"595b43d16e4b7305e5b40845",
"595b459a6e4b7305e5b40848",
"595f48f58117c85e041f1e1c",
],
}
This is my Pcard Scema
var PcardSchema = new Schema({
Time : {
type : Date,
default: Date.now
},
})
I want to find user having Id and which also contains some id in Pcard array
User.find({ _id: req.user._id,
Pcard:{$in : [req.params.PcardId] }
}, function (err, Userpresent) {
if (err) {
res.json(code.Parked);
}
if (Userpresent === null || Userpresent === undefined) {
res.json(code.notAllowed);
}else{
This else is execting everytime.
}
}
});
when i querying with user which does not have a Pcardid in Pcard array it is still going in else condition !
for eg . i am querying with this id 59560bc83e1fdc2cb8e73236 and this not contain 5957bd177e996b56d08b991a in Pcard array but still it is going on else part of the user query.
If you are expecting only one user, use findOne.
Might be useful/cleaner for you to return early instead of having a bunch if-else.
User.findOne({
_id: req.user._id,
Pcard: { $in : [req.params.PcardId] }
}, function (err, user) {
if (err) {
return res.json(code.Parked);
}
// simplified: undefined and null are both falseys
if (!user) {
return res.json(code.notAllowed);
}
// user should be found at this point
});
Good read: All falsey values in JavaScript

I am trying to get a single array value from mongodb, but when i try i get the whole object

1.I Don't get the Item in Electro Array but the whole doc
getItem(data){
dbswap.findOne(
{ 'swap.Items.Electro.id':data.id,
'swap.Items.Electro.id':data.id }, function(err,item){
if(err){
return (err);
}
if(item){
console.log(item);
}
});
} // EOF
This is my Schema
1.I am trying to get the item i create in Electro only, I don't want the whole object i am getting at the moment.
var swapSchema = new mongoose.Schema({
swap: {
name: String,
Items: {
Electro: [
{
name: String,
info: String,
price: Number,
dateCreated: Date,
category: String,
id: Number
}
]
}
}
});
Use the projection field :
If you want to get all the array :
dbswap.findOne(
{ 'swap.Items.Electro.id':data.id},
{ 'swap.Items.Electro' : 1}
, function(err, obj){
will return something like :
{
_id: ObjectId("sdfsdfsdf"),
Electro:[{....},{....}]
}
Or if you want only the object in the array who match the query :
dbswap.findOne(
{ 'swap.Items.Electro.id':data.id},
{ 'swap.Items.Electro.$' : 1}
, function(err, obj){
will return something like :
{
_id: ObjectId("sdfsdfsdf"),
Electro:{your match object}
}

Resources