How to remove an entire array in mongodb- node - javascript

This is what I tred
removeFromCart:(userId)=>{
return new Promise(async (resolve,reject)=>{
db.get().collection(collection.CART_COLLECTION).updateOne({_id:userId},
{
$pull:{
products
}
}
)
resolve(response)
})
}
This is the structure of my database, after placing the orde, I have to remove the cart array , Then what I have to do?
{
"_id": {
"$oid": "633abca2f9a57f6470904812"
},
"user": {
"$oid": "633ab3c11e6e97b6332f56a1"
},
"products": [
{
"item": {
"$oid": "63314b0c07e279ee33c55caf"
},
"quantity": 2
}
]
}

You can use the $unset operator:
db.collection.update({
"_id": "633abca2f9a57f6470904812"
},
{
"$unset": {
"products": ""
}
})
Here's an example on mongoplayground: https://mongoplayground.net/p/X9jEnmKjCGK

Related

My api code retrieves an empty data array from mongodb while the code works well on mongodb playground

My mongodb database includes a collection of users and each user has an array of shops and each shop has an array of products. Here is a simplified version of my collection structure:
[
{
"_id": "60e66b70da2439232e330415",
"name": "User1 Name",
"shops": [
{
"_id": "60e7c9e2be0d8f03544a03b8",
"shopName": "User1 Shop1 Name",
"products": [
{
"_id": "60e9e9e8105d6021a2e91535",
"title": "User1 Shop1 Product1 Title"
},
{
"_id": "60e9f4a0105d6021a2e91536",
"title": "User1 Shop1 Product2 Title"
}
]
},
{
"_id": "60e8e8c00f3986577cb968c9",
"shopName": "User1 Shop2 Name",
"products": [
{
"_id": "60e9f4fe105d6021a2e91537",
"title": "User1 Shop2 Product1 Title"
},
{
"_id": "60e9f515105d6021a2e91538",
"title": "User1 Shop2 Product2 Title"
}
]
}
]
},
{
"_id": "60e66b93da2439232e330416",
"name": "User2 Name",
"shops": [
{
"_id": "60e69698e76cad44e49e1fc8",
"shopName": "User2 Shop1 Name",
"products": [
{
"_id": "60e9f588105d6021a2e91539",
"title": "User2 Shop1 Product1 Title"
},
{
"_id": "60e9f59c105d6021a2e9153a",
"title": "User2 Shop1 Product2 Title"
}
]
},
{
"_id": "60e902b441e9df63c7fbcb49",
"shopName": "User2 Shop2 Name",
"products": [
{
"_id": "60e9f5c9105d6021a2e9153b",
"title": "User2 Shop2 Product1 Title"
},
{
"_id": "60e9f5de105d6021a2e9153c",
"title": "User2 Shop2 Product2 Title"
}
]
}
]
}
]
I have an api endpoint like .../api/products/60e9f5de105d6021a2e9153c. This endpoint includes a parameter which is a productId. I have the following two codes to retrieve the product data from my mongodb collection, but the retrieved array is empty.
My endpoint code:
app.get("/api/products/:productId", (req,res)=>{
let productId = req.params.productId;
myData.getProductByProductId(productId)
.then(products => res.json(products))
.catch(err => res.json({"message": err}));
});
My DataService code:
getProductByProductId: function (productId) {
return new Promise((resolve, reject) => {
User.aggregate([
{
$match: {
"shops.products._id": productId
}
},
{
"$unwind": "$shops"
},
{
"$unwind": "$shops.products"
},
{
$match: {
"shops.products._id": productId
}
},
{
$project: {
"_id": "$shops.products._id",
"title": "$shops.products.title"
}
}
])
.exec().then(products => {
resolve(products)
}).catch(err => {
reject(err);
});
});
}
The aggregate code works well in this playground but in my web app code retrieves an empty array.
Turns out the casting of the ObjectId seemed to be the issue. We need to use mongoose.Types.ObjectId
The API code will looks like this
getProductByProductId: function (productId) {
return new Promise((resolve, reject) => {
User.aggregate([
{
$match: {
"shops.products._id": mongoose.Types.ObjectId(productId)
}
},
{
"$unwind": "$shops"
},
{
"$unwind": "$shops.products"
},
{
$match: {
"shops.products._id": mongoose.Types.ObjectId(productId)
}
},
{
$project: {
"_id": "$shops.products._id",
"title": "$shops.products.title"
}
}
])
.then(products => {
resolve(products)
}).catch(err => {
reject(err);
});
});
}

How to change field from subdocument a parent field in Mongoose

I am trying to export Mongo data to XLSX which requires all the data to be in the parent map but currently I have data in this format:
[
{
"_id": "eatete",
"competition": {
"_id": "eatete"
"name": "Some competition name"
},
"members": [
{
"_id": "eatete",
"name": "Saad"
},
{
"_id": "eatete",
"name": "Saad2"
}
],
"leader": {
"name": "Saad",
"institute": {
"_id": "eatete",
"name": "Some institute name"
}
},
}
]
Ideally, the data should be:
[
{
"_id": "eatete",
"competition": "Some competition name"
"member0name": "Saad",
"member1name": "Saad2",
"leadername": "Saad",
"institute": "Some institute name"
}
]
So basically what I want is to refer the data of fields of subdocuments as if those were part of parent document, like competitions = competitions.name.
Can you please help me how can I do so using Mongoose.
Thanks
With some more aggregation trick
db.collection.aggregate([
{ "$unwind": { "path": "$members", "includeArrayIndex": "i" }},
{ "$group": {
"_id": "$_id",
"competition": { "$first": "$competition.name" },
"leadername": { "$first": "$leader.name" },
"institute": { "$first": "$leader.institute.name" },
"data": {
"$push": {
"k": { "$concat": ["members", { "$toLower": "$i" }, "name"] },
"v": "$members.name"
}
}
}},
{ "$replaceRoot": {
"newRoot": {
"$mergeObjects": ["$$ROOT", { "$arrayToObject": "$data" }]
}
}},
{ "$project": { "data": 0 }}
])
You can try below aggregation on your Model:
let resultt = await Model.aggregate([
{
$project: {
_id: 1,
competition: "$competition.name",
leadername: "$leader.name",
institute: "$leader.institute.name",
members: {
$map: {
input: { $range: [ 0, { $size: "$members" } ] },
in: {
k: { $concat: [ "member", { $toString: "$$this" }, "name" ] },
v: {
$let: {
vars: { current: { $arrayElemAt: [ "$members", "$$this" ] } },
in: "$$current.name"
}
}
}
}
}
}
},
{
$replaceRoot: {
newRoot: {
$mergeObjects: [ "$$ROOT", { $arrayToObject: "$members" } ]
}
}
},
{
$project: {
members: 0
}
}
])
Since you need to dynamically evaluate your keys based on indexes you can use $map with $range to map a list of indexes into keys of a new object. Then you can use $arrayToObject to get an object from those keys and $mergeObjects with $replaceRoot to flatten this object structure.

Unwind 2 arrays separately without using $facet in mongodb 3.2x

Objective: I need to pull out posts and shares and sort then according to date and time and put them together into a single array of Objects
{
"_id": {
"$oid": "5919e1f8b1f75c2b1cb504ea"
},
"user": {
"$oid": "58deb7db5aac7a0011d7bdf4"
},
"likes": [],
"comments": [],
"posts": [
{
"p_Id": {
"$oid": "596b16b1c657d21d8048287d"
},
"Date": {
"$date": "2017-07-16T07:33:06.238Z"
}
},
{
"p_Id": {
"$oid": "596b3068183c4f24d853f228"
},
"Date": {
"$date": "2017-07-16T09:22:49.451Z"
}
}
],
"__v": 331,
"shares": [
{
"sh_Id": {
"$oid": "596b2d65d65e092778a41e31"
},
"Date": {
"$date": "2017-07-16T09:09:57.666Z"
}
},
{
"sh_Id": {
"$oid": "596b2d9e371b5c2194775c0d"
},
"Date": {
"$date": "2017-07-16T09:10:54.701Z"
}
}
]
}
Desired Result:
[ {
"p_Id": {
"$oid": "596b16b1c657d21d8048287d"
},
"Date": {
"$date": "2017-07-16T07:33:06.238Z"
}
},
{
"sh_Id": {
"$oid": "596b2d65d65e092778a41e31"
},
"Date": {
"$date": "2017-07-16T09:09:57.666Z"
}
},
{
"sh_Id": {
"$oid": "596b2d9e371b5c2194775c0d"
},
"Date": {
"$date": "2017-07-16T09:10:54.701Z"
}
},
{
"p_Id": {
"$oid": "596b3068183c4f24d853f228"
},
"Date": {
"$date": "2017-07-16T09:22:49.451Z"
}
},
{
"p_Id": {
"$oid": "596b3071183c4f24d853f229"
},
"Date": {
"$date": "2017-07-16T09:22:57.911Z"
}
}]
My Query:
Activity.aggregate([
{ $match : { user : mongoose.Types.ObjectId(data.user) } },
{ $unwind: "$posts" }, { $unwind: "$shares"},
{ $project : { _id: 0, posts: 1, shares: 1 } }
]).exec(function(err,result){
console.log(result);
});
But this query gives results in pairs. i.e. in subdocument the same post occurs for each share.for e.g.
My Result:
[ { posts:
{ p_Id: 596b16b1c657d21d8048287d,
Date: 2017-07-16T07:33:06.214Z },
shares:
{ sh_Id: 596b2d65d65e092778a41e31,
Date: 2017-07-16T09:09:57.666Z } },
{ posts:
{ p_Id: 596b16b1c657d21d8048287d,
Date: 2017-07-16T07:33:06.214Z },
shares:
{ sh_Id: 596b2d9e371b5c2194775c0d,
Date: 2017-07-16T09:10:54.701Z } },
{ posts:
{ p_Id: 596b16b1c657d21d8048287d,
Date: 2017-07-16T07:33:06.214Z },
shares:
{ sh_Id: 596b30c1183c4f24d853f22c,
Date: 2017-07-16T09:24:17.621Z } }]

Why the following query does not return any data?

I have a collection in mongodb and indexed on the field name , i do a free search using the following query to get matched results and limit to 5,
db.getCollection('_event').aggregate([
{
"$match": {
"$and": [
{
"$text": {
"$search": "liver"
}
},
{},
{}
]
}
},
{
"$group": {
"_id": null,
"count": {
"$sum": 1
},
"results": {
"$push": "$$ROOT"
}
}
},
{
"$project": {
"count": 1,
"results": {
"$slice": [
"$results",
5
]
}
}
}
])
but there is a data with liverpool . when i do replace it with "$search": "liverpool" it returns data.
what is the issue here?

Mongoose findOneAndUpdate inside nested Arrays

I need to update the type, key and values in the 'fields' array if the componentId and the wfInstanceId id matches.
This is the document that i need to do so.
{
"_id": {
"$oid": "586b6d756937c22f207dd5af"
},
"wfInstanceId": "0111",
"workflowId": "ash3",
"folderURL": "ash3",
"teamName": "teamName",
"dataStream": [
{
"componentInstanceId": "componentInstanceId1",
"componentId": "componentId1",
"_id": {
"$oid": "586b6d756937c22f207dd5b0"
},
"fields": [
{
"type": "String",
"value": "value1",
"key": "key",
"_id": {
"$oid": "586b6d756937c22f207dd5b1"
}
},
{
"type": "String",
"value": "value2",
"key": "key1",
"_id": {
"$oid": "586b6d756937c22f207dd5b1"
}
}
]
},
{
"componentInstanceId": "componentInstanceId2",
"componentId": "componentId22",
"_id": {
"$oid": "586b6d756937c22f207dd5b0"
},
"fields": [
{
"type": "String",
"value": "value1",
"key": "key",
"_id": {
"$oid": "586b6d756937c22f207dd5b1"
}
},
{
"type": "String",
"value": "value2",
"key": "key2",
"_id": {
"$oid": "586b6d756937c22f207dd5b1"
}
}
]
}
],
"id": "38f356f0-d196-11e6-b0b9-3956ed7f36f0",
"__v": 0
}
I tried this like this, Also i tried $set over $push which is also doesn't work.
Model.findOneAndUpdate( {'wfInstanceId': '0111', 'dataStream.componentId': 'componentId1'}, {$push : { 'dataStream.fields.$.key' : 'sdsdds' }}, { upsert: true }, function (err, data) {
if (err) {
reject(err);
console.log('error occured' + err);
}
console.info("succesfully saved");
resolve (data);
});
As they describe in this DOC it shouldbe working for update method that is also didn't work for me. Any help will be really appreciated to overcome this issue i'm facing.
As you are using $ operator it updates only the first matched array element in each document.
As of now it is not possible in mongoose to directly update all array elements.
You can do this in your case:
db.collection.find({'wfInstanceId': '0111', 'dataStream.componentId': 'componentId1'})
.forEach(function (doc) {
doc.datastream.forEach(function (datastream) {
if (dataStream.componentId === componentId1) {
dataStream.fields.forEach(function(fields){
// you can also write condition for matching condition in field
dataStream.fields.key="";
dataStream.fields.value="";
dataStream.fields.type="";
}
}
});
db.collection.save(doc);
});
It is normal javascript code. I think it's clearer for mongo newbies.

Categories

Resources