updating a data object in nested array in mongodb by mongoose - node.js

i have a serious problem in updating my data . i have no idea how i can update a specific field in an object of an array in my document .
here is my Schema model :
var shiftSchema = new Schema({
Phone: String,
final: Boolean,
statusSH: String,
order: {
startTime: String,
finishTime: String,
income: String,
orders: [{
stat: String,
orderId: String,
customerPhone: String,
orderQuantity: String,
orderCost: String,
orderCondition: String,
orderTag: String
}]
}
});
when i use "find" it gives me the document and not just the object.
now how can i edit "stat" by finding "orderId" ?
Note that i do not have the index of the object that i want to update and i can just use "find"or "findOne".
i search all over the web and i couldn't find a good guide and example .
sorry for my bad english.
All tips will be appreciated. Thank You.

You can try to run this query, to update the stat property:
shiftSchema.updateOne({
'order.orders.orderId': 'id'
}, {
'$set': {'order.orders.$.stat': 'newStatus'}
})
.then((result) => {
console.log(result)
}, (e) => {
console.log(e)
})
You can see I used positional $ operator to access an element in the array and update it without specifying the position of the element (with index).
I also used $set to replace the value of a field.
With just find or findOne you will not make the actual update.

Related

How to insert Array of objects in mongoDB?

I am very new to MONGO DB so please bear with me.I am having a problem my array of objects is not working properly .
Here is my schema
const playerSchema = new mongoose.Schema({
name: String,
stats :{
wins:Number,
losses:Number,
xp:Number
},
achievement:[
{
name:String,
date: String
}
] });
Here is my document
const fluffy = new playerModel({
"name":"nic raboy",
"stats":{
"wins":5,
"losses":10,
"xp":300
},
"achievements":[
{"name":"Massive XP","date" :"25-08-21"},
{"name":"instant loss","date":"24-08-21"}
]
});
however in mongodb atlas its only showing array...and i cant see the objects inside...
SCREENSHOT
Your schema is correct, it seems your input is wrong,
In schema definition you named it achievement, whereas in input document it is achievements. Correct this everything will work as you expected.
Explanation
The schema is expecting achievement and you inserted achievements, that is why it is shown as an empty array in the database. To avoids this kind of typos in the future, use the required flag.
const playerSchema = new mongoose.Schema({
name: String,
stats: {
wins: Number,
losses: Number,
xp: Number
},
achievements: [
{
name: {
type: String,
required : true,
},
date: {
type: String,
required : true, // required informs for missing fields
}
}
]
})
Refer this link for more on validation
You can use insertMany see the doc here.
Of course, a while loop should work find calling multiple times insertOne, though I advise you to use the insertMany() method.
If you're new to MongoDB, I strongly encourage you to have a look at MongoDB University's MongoDB basics course as well as the MongoDB for JavaScript Developers course.

How to find an object inside an array inside a mongoose model?

I'm trying to query an object that's inside an item which is inside a mongoose model, when I'm trying to find that object with the find() method or _.find() method, I can't get access to the object for some reason and when I console.log() it, it gives me undefined or when I use array.filter() it gives me an empty array, which means the object that I'm trying to access does not meet the criteria that I give it in the lodash find method, but then when I look at my database I see that the object does actually have the properties to meet the criteria. So I don't know what I'm doing wrong, here's my code: as you can see I'm trying to get the information of the item that the user clicked on and want to see:
router.get("/:category/:itemId", (req, res) => {
console.log(req.params.itemId);
//gives the item id that the user clicked on
console.log(req.params.category);
//gives the name of category so I can find items inside it
Category.findOne({ name: req.params.category }, (err, category) => {
const items = category.items; //the array of items
console.log(items); //gives an array back
const item = _.find(items, { _id: req.params.itemId });
console.log(item); //gives the value of 'undefined' for whatever reason
});
});
The category Schema:
const catSchema = new mongoose.Schema({
name: {
type: String,
default: "Unlisted",
},
items: [
{
name: String,
price: Number,
description: String,
img: String,
dateAdded: Date,
lastUpdated: Date,
},
],
dateCreated: Date,
lastUpdate: Date,
});
well the answer is a little bit obvious, you are using MongoDB and in Mongo you have "_ID" you can use that "_ID" only with Mongoose! so you just have to remove the underscore and that is it! do it like this const item = _.find(items, { id: req.params.itemId });
hope you are doing better.
When I look at your Schema I see that the item field is an array of objects which doesn't have an _id inside so when you create a new instance of catShema it just generates an _id field for the new instance but not for each item inside the items array, just also enter the id of the item in question because according to my understanding, you must also have a model called items in your database
When you save these records in your database, you will generate an element with this structure
{
_id: String, // auto generated
name: String,
items: [ {"name1", "price1", "description1", "imgUrl1", "dateAdded1", "lastUpdated1"},{"name2", "price2", "description2", "imgUrl2", "dateAdded1", "lastUpdated2"}, ...],
dateCreated: Date,
lastUpdate: Date
}
Note : the code provided at the top is only an illustration of the object which will be registered in the database and not a valid code
Here you can notice that there is not a field called _id in the object sent inside the database.
My suggestion to solve this issue is
To create an additional field inside the items array called _id like :
{
...,
items: [
{
_id: {
type: String,
unique : true,
required: true // to make sure you will always have it when you create a new instance
},
...
... // the rest of fields of items
},
...
Now when you create a new instance make sure in the object you enter in the database the _id is recorded when you call the catInstance.save() so inside the catInstance object you have to add the current Id of the element to be able to filter using this field.
Hope my answer helped, if you have any additional questions, please let me know
Happy coding ...

check and update nested documents in mongoose mongodb

i am new in mongodb and mongoose and i don't know how i can change an object in array which is in other object .
here is simple version of my schema
const shiftSchema = new Schema({
phone: String,
order: {
startTime: String,
finishTime: String,
orders: [{
stat: boolean,
orderId: Number
}]
}
});
orderId is actually the time every 5 so first object in orders has startTime+5 value as orderId and the last one has finishTime value.
so now i want to find the doc that has for example 0911111 as phone , 04090405 as startTime , 04090900 as finishTime , and inside it i want to update just the object that it's orderId is 04090435 if it's stat was false and also update 2 objects before it . which are 04090430 and 04090425 and also check their stat to be false and if even one of these 3 objects has true stat do not update it and send error.
i know it has answered many times but i can't find any solution for mine in specific conditions ,so please help me.
Note: i know that for updating this kind of arrays i can do something like this :
Shift.updateOne({
'order.orders': {$elemMatch: {orderId: {$lte: start}, stat: "true"}}
}, {
'$set': {'order.orders.$.stat': 'ready'}
})
but it just update whole Shift Collection but i only just want to update one doc.
All tips will be appreciated. Thank You

how to dynamically query in mongoose?

so I'm new to Programming and Mongoose, just learning the basics.
and now I get the task to make a dynamic query with criteria such as
query => gets all the data I input into the query in the parameter
example:
query: [ios, android] => i get all ios data, and android
query_else => gets all the data I input other than the parameter in the query
example:
query_else: [ios, android] => I got all the data OTHER ios and android
if I try to use .find, I can only get 1 specific data I'm looking for, but it can't if I enter 2 queries in it the results are []
maybe it's not the answer I want to look for, but how to think about solving this case, because of my lack of knowledge about mongoose and my lack of knowledge about coding that makes me deadlock thinking
Thank you in advance
account log schema in activity-log collection:
const actLogSchema = new Schema(
{
account_id: {
type: Schema.Types.ObjectId,
ref: 'account'
},
date_created: { type: String, default: Date.now() },
ip: String,
location: String,
device: String,
type: String,
label: String,
action: String,
description: String
},
{ versionKey: false }
);
i assume query is part of {date_created, ip, location, device, type, action, label, description}
and query_else is equal to query but the different it is values.. like the example above

How to get and update a specific object inside an array with Mongoose?

I'm having real trouble with MongoDB and Mongoose queries. The thing is, I have this Menu schema:
var menuSchema = new Schema({
userID: String,
name: String,
meals: [{
day: Number,
hour: Number,
minute: Number,
aliments: [{
name: String,
amount: Number,
}],
}],
});
So I'd like to know how to get a specific meal or aliment and how to update them throught the _id value, automatically generated when I add them.
Thank you so much.
David.
I finally could get it working for meals, but not for aliments. I'm doing this for meals:
Menu.update({_id: request.params.menu_id, 'meals._id': request.params.meal_id}, {'meals.$.hour': request.body.hour)}, function(error, affected, raw) {
response.send(error);
});
And this for aliments:
Menu.update({_id: request.params.menu_id, 'meals.aliments._id': request.params.aliment_id}, {'meals.aliments.$': {name: request.body.name, amount: request.body.amount}}, function(error, affected, raw) {
response.send(error);
});
EDIT: ok so I looked for an answer on other posts and I found out the solution.
Looks like the $ positional operator does NOT work with multi-level arrays. Actually, it works only for 1-level arrays (that's why it works for meals but it doesn't for aliments).
So I guess the solution is splitting meals or aliments in documents and reference them with a mealID or alimentID.
I hope they add multi-level positional operator soon. It would be great.

Resources