Mongoose, update of child will affect all parents? - node.js

What is the query to update below data with mongoose. So 3 fields are going to be updated. Top Parent Points, Categories Points and Tag Points.
{
"_id": "561fba5e7fac41a4055fad45",
"fullName": "Test",
"points": 45,
"level": 1,
"categories": [
{
"name": "Computer Science",
"points": 15,
"level": 1,
"_id": "561fba5e7fac41a4055fad46",
"tags": [
{
"name": "C#",
"points": 10,
"level": 1,
"_id": "561fba5e7fac41a4055fad47"
},
{
"name": "Java",
"points": 5,
"level": 1,
"_id": "561fba5e7fac41a4055ert12"
}
]
},
{
"name": "History",
"points": 30,
"level": 2,
"_id": "562407d4e3edf2113f61ac37",
"tags": [
{
"name": "WW2",
"points": 30,
"level": 2,
"_id": "56240797e3edf2113f61ac36"
}
]
}
]
}
to this one. When user gets a point from a specific tag, it will effect all parents. Let's say, user gets 10 points from C# then i have to update mongodb to this.
{
"_id": "561fba5e7fac41a4055fad45",
"fullName": "Test",
**"points": 55,**
"level": 1,
"categories": [
{
"name": "Computer Science",
**"points": 25,**
"level": 1,
"_id": "561fba5e7fac41a4055fad46",
"tags": [
{
"name": "c#",
**"points": 20,**
"level": 1,
"_id": "561fba5e7fac41a4055fad47"
},
{
"name": "Java",
"points": 5,
"level": 1,
"_id": "561fba5e7fac41a4055ert12"
}
]
},
{
"name": "History",
"points": 30,
"level": 2,
"_id": "562407d4e3edf2113f61ac37",
"tags": [
{
"name": "WW2",
"points": 30,
"level": 2,
"_id": "56240797e3edf2113f61ac36"
}
]
}
]
}

you should use $elemMatch for querying your object
db.tests.update({_id: yourTestId, categories: {$elemMatch: {_id: categoryId}}}, {$set: {$inc: {"categories.$.points": 10, points: 10}}})
So you querying only needed array element and update it values with $ reference

Related

is there any mongo db query to only add new elements the nested elements by id

my data structure is and products elements all tags in empty
I need to add a value to mongo db inner object with array element without looking at other value. Can some one advice to do this.
[
{
"item": "journal",
"id": 11,
"products": [
{
"id": 3,
"name": "p one",
"tags": []
}
]
},
{
"item": "notebook",
"id": 14,
"products": [
{
"id": 4010,
"name": "item-five",
"tags": []
}
]
}
]
and I want to add tag in products elements with match product id '4010', so the expected response should be like
[
{
"item": "journal",
"id": 11,
"products": [
{
"id": 3,
"name": "p one",
"tags": []
}
]
},
{
"item": "notebook",
"id": 14,
"products": [
{
"id": 4010,
"name": "item-five",
"tags": [
{
"id": 21,
"key": "tag-one",
"name": "tag-one",
}
]
}
]
}
]
You should look at arrayFilter option https://www.mongodb.com/docs/v6.0/reference/operator/update/positional-filtered/#update-all-documents-that-match-arrayfilters-in-an-array
Something like this might do the trick.
db.collection.updateMany(
{ },
{ $push: { "products.$[x].tags": {
"id": 21,
"key": "tag-one",
"name": "tag-one",
} } },
{ arrayFilters: [{ "x.id": 4010 }] }
);

How to filter the response from mongoDB, so nested arrays will include only items that meet a condition?

My documents look like this
{
"_id": {
"$oid": "62825f71005ce00c5f0235c1"
},
"user": "jon",
"roles": {
"User": 2001,
},
"STOCK ": [
{
"sku": "BLACK-M",
"productname": "BLACK",
"sendout": 0,
"recived": 1,
"totalinstock": 40,
"location": "B32",
"_id": {
"$oid": "62826016005ce00c5f0235c8"
}
},
{
"sku": "CJNS",
"productname": "89796363",
"sendout": 0,
"recived": 45,
"totalinstock": 0,
"location": "B232",
"_id": {
"$oid": "62836f2d56b4f1ac79c99b8d"
}
}
],
"ORDERS": [
{
"date": {
"$date": "2022-06-02T15:23:58Z"
},
"OrderNumber": "745607",
"City": "xxxxx",
"Address": "yyyyyy",
"Phone": "8678678678",
"Name": "Holly ",
"Trackingnumber": 40,
"ZipCode": 00000,
"Province": "New ",
"Quantity": [
1
],
"Product_Name": [
" pants pants"
],
"SKU": [
"CJNS"
],
"_id": {
"$oid": "6298d61ba6eeec72b78332a7"
}
},
{
"date": {
"$date": "2022-06-02T15:23:58Z"
},
"OrderNumber": "748840",
"City": "xxxxx",
"Address": "yyyyyy",
"Phone": "354353454",
"Name": "Michael",
"Trackingnumber": 0,
"ZipCode": 00000,
"Province": "North",
"Quantity": [
1
],
"Product_Name": [
" pants pants"
],
"SKU": [
"CJNS"
],
"_id": {
"$oid": "6298d61ba6eeec72b78332a9"
}
}
]
}
I successful to return all the objects in STOCK or all the objects in ORDERS
Through this query
const foundUser= await User.find({"user":req.body.user},("Orders") ).exec()
Now I want to filter the response to include only items where "Trackingnumber" is different from 0
For the sample data I expect to receive only
{
"date": {
"$date": "2022-06-02T15:23:58Z"
},
"OrderNumber": "748840",
"City": "xxxxx",
"Address": "yyyyyy",
"Phone": "354353454",
"Name": "Michael",
"Trackingnumber": 0,
"ZipCode": 00000,
"Province": "North",
"Quantity": [
1
],
"Product_Name": [
" pants pants"
],
"SKU": [
"CJNS"
],
"_id": {
"$oid": "6298d61ba6eeec72b78332a9"
}
}
You can use an aggregation pipeline with a $filter for this:
db.collection.aggregate([
{
$match: {
"user": "jon"
}
},
{
$project: {
ORDERS: {
$filter: {
input: "$ORDERS",
as: "item",
cond: {$ne: ["$$item.Trackingnumber", 0]}
}
}
}
}
])
Playground example
User.find({"Orders" : {"Trackingnumber": 0} })

How to add orders array in product

Whenever a customer checks out its saves an order that has products ordered by a customer and the product id, quantity and customers details like delivery address and customer phone number.
I want the same details to be added to all products in that order also so that the seller can also see that his product has been ordered
This i can achieve using each product's id in the orders since every product has its ID . But i dont know how to map the order's products id's and find the products in the products schema then add to them an array called orders.
This is how my orders schema looks like after an order has been placed
{
"allOrders": [
{
"_id": "6249ee9baa59aceb7d88f91d",
"placedby": "624471321dff6794a802431c",
"fullname": "Collins Jimu",
"deliveryaddress": "cnr fourth and herbet chitepo",
"phonenumber": "0773468496",
"whatsappphonenumber": "0773468496",
"ordersList": [
{
"name": "Hp 200 G4Core I5",
"qty": 1,
"price": 560,
"imgUrl": "https://res.cloudinary.com/kwingy/image/upload/v1648734312/cwynmzauqqnylrwsgejy.jpg",
"id": "6245b0c09390975e16263136"
},
{
"name": "bed",
"qty": 1,
"price": 160,
"imgUrl": "https://res.cloudinary.com/kwingy/image/upload/v1648732217/dtrb8saj0ellgyrcjpyy.jpg",
"id": "6245a88cf22df558d8d69162"
},
{
"name": "Sunglass",
"qty": 1,
"price": 6,
"imgUrl": "https://res.cloudinary.com/kwingy/image/upload/v1648738341/rtpiptqc1le6kywmuisf.jpg",
"id": "6245c03bf22df558d8d6a739"
},
{
"name": "sofas",
"qty": 1,
"price": 890,
"imgUrl": "https://res.cloudinary.com/kwingy/image/upload/v1648732837/xae655b5e9wovodfkvqn.jpg",
"id": "6245aacdf22df558d8d6939f"
}
],
"paymentmethod": "cashondeliver",
"orderstatus": "placed",
"createdAt": "2022-04-03T18:59:39.681Z",
"updatedAt": "2022-04-03T18:59:39.681Z",
"__v": 0
},
{
"_id": "6249fdc602cefac4faa36dde",
"placedby": "624471321dff6794a802431c",
"fullname": "My MUM",
"deliveryaddress": "123 HARARE STREET",
"phonenumber": "0773550804",
"whatsappphonenumber": "0773550804",
"ordersList": [
{
"name": "out door benches",
"qty": 1,
"price": 25,
"imgUrl": "https://res.cloudinary.com/kwingy/image/upload/v1648736078/in8rumwcm6rrebrmgb1q.jpg",
"id": "6245b792be41db13f9220867"
},
{
"name": "hammer",
"qty": 1,
"price": 10,
"imgUrl": "https://res.cloudinary.com/kwingy/image/upload/v1648735570/joceetdkx4penomtab8s.jpg",
"id": "6245b5849390975e16263647"
},
{
"name": "Watches",
"qty": 1,
"price": 4,
"imgUrl": "https://res.cloudinary.com/kwingy/image/upload/v1648735962/r4jmwlj7ltgc0njdtfdc.jpg",
"id": "6245b71abe41db13f92207ac"
},
{
"name": "iPhone X",
"qty": 1,
"price": 350,
"imgUrl": "https://res.cloudinary.com/kwingy/image/upload/v1648729600/ekcb86lmtkr0uniirb2i.jpg",
"id": "62459fc3be41db13f921f27a"
},
{
"name": "REFRIDGERATOR",
"qty": 1,
"price": 370,
"imgUrl": "https://res.cloudinary.com/kwingy/image/upload/v1648731962/fjrlvfnotdbonqnt9pjn.jpg",
"id": "6245a750be41db13f921f796"
}
],
"paymentmethod": "cashondeliver",
"orderstatus": "placed",
"createdAt": "2022-04-03T20:04:22.349Z",
"updatedAt": "2022-04-03T20:04:22.349Z",
"__v": 0
},
{
"_id": "624a12ea02cefac4faa431fd",
"placedby": "624471321dff6794a802431c",
"fullname": "Munyaradzi Makosa",
"deliveryaddress": "cnr fourth and herbet",
"phonenumber": "0777727363663",
"whatsappphonenumber": "0777727363663",
"ordersList": [
{
"name": "Wheels",
"qty": 1,
"price": 35,
"imgUrl": "https://res.cloudinary.com/kwingy/image/upload/v1648741496/xs9zpht0rhxpijrzyqrz.jpg",
"id": "6245cc859390975e162657ce"
},
{
"name": "MacBook Pro 2021",
"qty": 1,
"price": 1250,
"imgUrl": "https://res.cloudinary.com/kwingy/image/upload/v1648731661/h0dcvvhwntdy06mzgpah.webp",
"id": "6245a6649390975e16262737"
},
{
"name": "electric kettle",
"qty": 1,
"price": 22,
"imgUrl": "https://res.cloudinary.com/kwingy/image/upload/v1648734446/tyrdlrayn3opm7gagwmi.jpg",
"id": "6245b1239390975e162631e3"
}
],
"paymentmethod": "cashondeliver",
"orderstatus": "placed",
"createdAt": "2022-04-03T21:34:34.721Z",
"updatedAt": "2022-04-03T21:34:34.721Z",
"__v": 0
},
{
"_id": "624aa7cd02cefac4faa4750c",
"placedby": "624aa7a102cefac4faa474f3",
"fullname": "Ryan Katayi",
"deliveryaddress": "4164 Gwabalanda",
"phonenumber": "0718518438",
"whatsappphonenumber": "0718518438",
"ordersList": [
{
"name": "Budi 2017",
"qty": 1,
"price": 250,
"imgUrl": "/assets/images/products/Automotive/2.Audi2017.png",
"id": "6270512109915791"
}
],
"paymentmethod": "cashondeliver",
"orderstatus": "placed",
"createdAt": "2022-04-04T08:09:49.618Z",
"updatedAt": "2022-04-04T08:09:49.618Z",
"__v": 0
},
{
"_id": "624c0e770d2cf94693988609",
"placedby": "624aa7a102cefac4faa474f3",
"fullname": "Ryan Katayi",
"deliveryaddress": "4164 Gwabalanda",
"phonenumber": "0718518438",
"whatsappphonenumber": "0778687452",
"ordersList": [
{
"name": "Nike Airforce",
"qty": 2,
"price": 40,
"imgUrl": "https://res.cloudinary.com/kwingy/image/upload/v1649082553/hoodaley8bzrwa8xi2tr.jpg",
"id": "624b01250d2cf94693982652"
},
{
"name": "iPhone X",
"qty": 1,
"price": 350,
"imgUrl": "https://res.cloudinary.com/kwingy/image/upload/v1648729600/ekcb86lmtkr0uniirb2i.jpg",
"id": "62459fc3be41db13f921f27a"
}
],
"paymentmethod": "cashondeliver",
"orderstatus": "placed",
"createdAt": "2022-04-05T09:40:07.719Z",
"updatedAt": "2022-04-05T09:40:07.719Z",
"__v": 0
}
]
}
i have managed to get the ids of all the orders. But my challenge is i am stuck with only the products ids not sure how to use them and find each products and then patch them with an orders details array
const sellerProductsOrdered = asyncHandler (async (req, res) => {
const Orders = await Order.find();
const ordersList = Orders.map(order => {
return order
})
const ordersListProductsIds = ordersList.map(product => {
return product.id
})
console.log(ordersListProductsIds);
})

Populating all items from ref model [duplicate]

This question already has answers here:
$lookup multiple levels without $unwind?
(1 answer)
Mongoose: deep population (populate a populated field)
(10 answers)
Closed 3 years ago.
I have a database structured like this:
I want to get all listItems, of all lists from a user with a x ID. What's the correct way of doing that?
I'm using node with mongoose, and I tried the following:
await User.findById(user._id).populate('list');
But realized that I can't populate all ListItem's from that. Meaning, I can't do this:
await User.findById(user._id).populate('list').populate('listItem');
How can I get all listItems, of all lists from a user with a x ID?
Assuming User, List, and ListItem are Collections, you should be able to accomplish this using $lookup..
Here is a live demo of the following query..
Query:
db.users.aggregate([
{
$match: {
uniqueId: 1
}
},
{
$lookup: {
from: "lists",
localField: "uniqueId",
foreignField: "userId",
as: "lists"
}
},
{
$lookup: {
from: "listItems",
localField: "uniqueId",
foreignField: "userId",
as: "listItems"
}
}
])
Dataset:
db={ // Simulates a DB ********
"users": [ // Simulates a Collection ********
{
"firstname": "John",
"lastname": "Smith",
"email": "jsmith#gmail.com",
"password": "password123",
"uniqueId": 1
},
{
"firstname": "Jane",
"lastname": "Doe",
"email": "doe#yahoo.com",
"password": "123password",
"uniqueId": 2
}
],
"lists": [ // Simulates a Collection ********
{
"userId": 1,
"name": "Johns List 1",
"items": [
11,
12,
13
]
},
{
"userId": 2,
"name": "Groceries",
"items": [
21,
22,
23
]
}
],
"listItems": [ // Simulates a Collection ********
{
"userId": 2,
"itemId": 21,
"title": "Apple",
"notes": []
},
{
"userId": 2,
"itemId": 22,
"title": "Banana",
"notes": []
},
{
"userId": 2,
"itemId": 23,
"title": "Strawberry",
"notes": []
},
{
"userId": 1,
"itemId": 11,
"title": "Oil Change",
"notes": []
},
{
"userId": 1,
"itemId": 12,
"title": "Pick Up Grandma",
"notes": []
},
{
"userId": 1,
"itemId": 13,
"title": "Go For Run",
"notes": []
}
]
}
Result:
[
{
"_id": ObjectId("5a934e000102030405000008"),
"email": "jsmith#gmail.com",
"firstname": "John",
"lastname": "Smith",
"listItems": [
{
"_id": ObjectId("5a934e000102030405000003"),
"itemId": 11,
"notes": [],
"title": "Oil Change",
"userId": 1
},
{
"_id": ObjectId("5a934e000102030405000004"),
"itemId": 12,
"notes": [],
"title": "Pick Up Grandma",
"userId": 1
},
{
"_id": ObjectId("5a934e000102030405000005"),
"itemId": 13,
"notes": [],
"title": "Go For Run",
"userId": 1
}
],
"lists": [
{
"_id": ObjectId("5a934e000102030405000006"),
"items": [
11,
12,
13
],
"name": "Johns List 1",
"userId": 1
}
],
"password": "password123",
"uniqueId": 1
}
]

Query to retrieve every subdocument alone without passing parent id using Mongoose

Here i like to explain my problem.
How can i write a mongoose query to retrieve every subdocument from JSON without passing parent_id.
[
{
"_id": "56a320003fe17cc7363dd0d7",
"name": "Leanna Jacobson",
"gender": "female",
"friends": [
{
"id": 0,
"name": "Riley Case"
},
{
"id": 1,
"name": "Herman Carter"
},
{
"id": 2,
"name": "Pacheco Woodard"
}
]
},
{
"_id": "56a3200001501cfa1ea2641d",
"name": "Juliana Bonner",
"gender": "female",
"friends": [
{
"id": 0,
"name": "Keller Woodward"
},
{
"id": 1,
"name": "Fern Knight"
},
{
"id": 2,
"name": "Cain Richards"
}
]
},
{
"_id": "56a3200006864c78ecb1aeed",
"name": "Gena Stark",
"gender": "female",
"friends": [
{
"id": 0,
"name": "Kate Franco"
},
{
"id": 1,
"name": "Araceli Mcclure"
},
{
"id": 2,
"name": "Molly Nelson"
}
]
},
{
"_id": "56a320006d868155161038b6",
"name": "Eve Gonzalez",
"gender": "female",
"friends": [
{
"id": 0,
"name": "Pam Lang"
},
{
"id": 1,
"name": "Christy Marks"
},
{
"id": 2,
"name": "Donovan Warren"
}
]
},
{
"_id": "56a3200066b94852f5680568",
"name": "Coleman Wooten",
"gender": "male",
"friends": [
{
"id": 0,
"name": "Roberta Olson"
},
{
"id": 1,
"name": "Roseann Reid"
},
{
"id": 2,
"name": "Kerri Russell"
}
]
}
]
Here i need to retrieve every friends details from the subdocument array friends for every parent.
so how can i write query for this?????
Suppose the name of your schema is Person, try this one.
//find all document, only select `friends` field from every document
Person.find({}, 'friends', function (err, friends) {
// the return friends is the [[friends], [friends], ...]
});

Resources