$pulling an object from an array based on _id in Mongoose [duplicate] - node.js

Doc:
{
_id: 5150a1199fac0e6910000002,
name: 'some name',
items: [{
id: 23,
name: 'item name 23'
},{
id: 24,
name: 'item name 24'
}]
}
Is there a way to pull a specific object from an array? I.E. how do I pull the entire item object with id 23 from the items array.
I have tried:
db.mycollection.update({'_id': ObjectId("5150a1199fac0e6910000002")}, {$pull: {id: 23}});
However I am pretty sure that I am not using 'pull' correctly. From what I understand pull will pull a field from an array but not an object.
Any ideas how to pull the entire object out of the array.
As a bonus I am trying to do this in mongoose/nodejs, as well not sure if this type of thing is in the mongoose API but I could not find it.

try..
db.mycollection.update(
{ '_id': ObjectId("5150a1199fac0e6910000002") },
{ $pull: { items: { id: 23 } } },
false, // Upsert
true, // Multi
);

I have a document like
I have to delete address from address array
After searching lots on internet I found the solution
Customer.findOneAndUpdate(query, { $pull: {address: addressId} }, (err, data) => {
if (err) {
return res.status(500).json({ error: 'error in deleting address' });
}
res.json(data);
});

my database:
{
"_id" : ObjectId("5806056dce046557874d3ab18"),
"data" : [
{ "id" : 1 },
{ "id" : 2 },
{ "id" : 3 }
]
}
my query:
db.getCollection('play_table').update({},{$pull:{"data":{"id":3}}},{multi:true}
output:
{
"_id" : ObjectId("5806056dce046557874d3ab18"),
"data" : [
{ "id" : 1 },
{ "id" : 2 }
]
}

You can try it also:
db.getCollection('docs').update({ },{'$pull':{ 'items':{'id': 3 }}},{multi:true})

For a single record in array:
db.getCollection('documents').update(
{ },
{'$pull':{ 'items':{'mobile': 1234567890 }}},
{new:true}
);
For a multiple records with same mobile number in array:
db.getCollection('documents').update(
{ },
{
$pull: {
items: { mobile: 1234567890 }
}
},
{ new:true, multi:true }
)

Use $pull to remove the data
return this.mobiledashboardModel
.update({"_id": args.dashboardId}, { $pull: {"viewData": { "_id": widgetId}}})
.exec()
.then(dashboardDoc => {
return {
result: dashboardDoc
}
});

Kishore Diyyana:
If you want to remove all elements including the key of the element attributes list.
Here is the example of mongoDB unset operator:
db.UM_PREAUTH_CASE.update(
{ 'Id' : 123}, { $unset: { dataElements: ""} } )
JSON Look like this:
{ "Id":123,"dataElements" : [ { "createdBy" : "Kishore Babu Diyyana", "createdByUserId" : 2020 }, { "createdBy" : "Diyyana Kishore", "createdByUserId" : 2021 } ] }

Related

MongoDB update multiple items in an array of objects with corresponding data

I have an array in my MongoDB document as shown below:
{
...otherDocFields,
groupID: "group-id",
users: [
{id: "uid1", name: "User1"},
{id: "uid2", name: "User2"},
{id: "uid3", name: "User3"},
{id: "uid4", name: "User4"}
]
}
I'm trying to write a function that will update users' names based on that ID.
I tried something like:
async function updateNames(groupID: string, data: Array<{id: string, name: string}>) {
try {
// MongoDB Aggregation
await mongoDB.collection("users").aggregate([
{$match: {groupID}},
{$unwind: {
path: '$users',
includeArrayIndex: 'users.id',
preserveNullAndEmptyArrays: true
}
}
//....
])
} catch (e) {
console.log(e)
}
}
I'm stuck at the part to update the relevant names from the data param in the function.
A sample data would be:
[
{id: "uid1", name: "newName1"},
{id: "uid3", name: "newName3"}
]
I can for sure read, manually process it and update the document but I'm looking for a way to do it in single go using aggregation.
You can do this with an update statement using array filters (https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/#---identifier--)
First, if we just declare some tests data which would be passed into your method:
const data = [
{id: "uid2", name: "ChangeName1"},
{id: "uid4", name: "ChangedName2"}
];
We can then create an update statement which updates all the users within that list within a map and a reduce:
const sets = data.map((element, index) => ({ [`users.$[f${index}].name`]: element.name })).reduce((accumulator, currentValue) => (Object.assign(currentValue, accumulator)), { });
const update = { $set: sets };
This will give us the following update statement:
{
"$set" : {
"users.$[f1].name" : "ChangedName2",
"users.$[f0].name" : "ChangeName1"
}
}
We can create a bunch of array filters with that data:
const arrayFilters = data.map((element, index) => ({ [`f${index}.id`]: element.id }));
This will give us the following which we can pass into the options of an update.
[ { "f0.id" : "uid2" }, { "f1.id" : "uid4" } ]
Last of all we can execute the following update command:
db.users.updateOne(
filter,
update,
{ arrayFilters }
);
Now if we check the output we'll get the following results
> db.users.find().pretty()
{
"_id" : ObjectId("60e20841351156603932c526"),
"groupID" : "123",
"users" : [
{
"id" : "uid1",
"name" : "User1"
},
{
"id" : "uid2",
"name" : "ChangeName1"
},
{
"id" : "uid3",
"name" : "User3"
},
{
"id" : "uid4",
"name" : "ChangedName2"
}
]
}

deleting an object from array in mongo collection

I have a mongo schema like this.
{
userID:19202,
products:[ { id:020, name:'first' }]
}
I want to pop items from the product array based on id. I used the following command. although it didn't give any error, it also not deleting elements from an array.
userCart.updateOne(
{ userID:userID},
{ $pull: { products: { id:id } } }
)
.then((data) =>
{
if(data)
{
//data is {
"n": 1,
"nModified": 0,
"ok": 1
}
return res.json({
status:true,
message:"cart updated"
})
}
})
Demo - https://mongoplayground.net/p/mh6fXN21vyR
Make sure id and products.id are of the same type as in your document in the database. As your sample, both should be numbers.
if they both are number
db.collection.update({
userID: 19202
},
{
$pull: {
"products": { id: 20 }
}
})
Not Working here - https://mongoplayground.net/p/3zhv8yoH2o9 when "products": { id: "20" }. products.id is a string in the mongo query and in the database in number so mismatched.
Try this one:
db.userCart.update(
{ userID:userID },
{ $pull: { items: { id: 020 } } },
false, // Upsert
true, // Multi
);

MongoDB add field to an object inside an array

I have an object user that looks like that
{
"_id" : ObjectId("5edbdf57ac52325464b054ec"),
...
"purchaseHistory" : [
{
"_id" : ObjectId("5ee7a8f6b438a1254cec3f74"),
...
},
{
"_id" : ObjectId("5ee7a8f6b438a1254cec3f88"),
...
}
]
}
What I wanna do is to add a new field to a specific object inside "purchaseHistory" by ID, for example I wanna add to "5ee7a8f6b438a1254cec3f88" a field "status": 0
What I tried is
users.findOneAndUpdate(
{
_id: ObjectId(userId),
'purchaseHistory._id': ObjectId(saleId)
},
{
$set: { 'purchaseHistory.$.status': status}
}
)
But it gives me an error, how can I do it properly?
According to the website provided by D. SM, I was able to do it this way
users.findOneAndUpdate(
{
'_id': ObjectId(userId),
'purchaseHistory._id': ObjectId(saleId)
},
{
$set: { 'purchaseHistory.$.status': status }
}
)
MongoDB provides the positional update operator for cases like this.

Mongoose: update an element of an array of a specific document

I am having a collection of documents called 'company'.
company 1 -
{
_id: '1',
data:[
{_id:'11', value: 'emp11'},
{_id:'12', value: 'emp12'}
]
}
company 2-
{
_id: '2',
data:[
{_id:'21', value: 'emp21'},
{_id:'22', value: 'emp22'}
]
}
Now I want to update value 'emp11' to 'emp99'.
I'm following this approach-
companyModel.findById('1', function(err, company) {
return company.data.update(
{_id: '11'},
{$set: {value: 'emp99'}}
);
});
I'm able to get the company but after that it's showing an error-
company.data.update is not a function
Please suggest a possible solution.
companyModel.update(
{ "_id" : :"1", "data._id": "11" },
{ "$set": { "data.$.value": "emp99" }},
function(err, company) {
console.log(company)
})
There is no need to use findById, you can use this directly.
In mongo update you need to search for both the document and the field you want to update.
The field you want to update is essential as it is used to locate the position of the array when you use $.
However you can do it as following also :
companyModel.findById('1', function(err, company) {
for(var i =0; i< company.data.length; i++)
if(company.data._id === "11")
break;
if(i<company.data.length)
company.data[i].value = 'emp99'
company.save()
});
db.company.update({
_id: "1",
data: {
$elemMatch: {
value: 'emp11'
}
}
}, {
$set: {
'data.$.value': 'emp99'
}
})

Conflict when updating a document with both $set and $currentDate

I’m using Mongo 3.6.3 and I have a database with a collection and an item with _id equal to 1.
I want to update the item by adding an object and a timestamp inside of that object. However, I get an error. Here’s what I do:
function MyObject() {
this.bar = {
apples: 4,
bananas: 5
};
}
collection.update({
_id: 1
}, {
$set: {
"foo": new MyObject()
},
$currentDate: {
"foo.time": {
$type: 'timestamp'
}
}
}, function (err) {
console.log(err.name, err.message);
});
and I get:
MongoError Updating the path 'foo.time' would create a conflict at 'foo'
Why does that happen?
If I run the $set operation first and then the $currentDate one in another update(), I get the desired result:
{
"_id" : 1,
"foo" : {
"bar" : {
"apples" : 4,
"bananas" : 5
},
"time" : Timestamp(1523459420, 1)
}
}
However, if I try to do them simultaneously like I’ve shown in the code above, I get the error. Why?
You can't have multiple operators ($set and $currentDate) that modify the same path (foo in this case). In your case you could use dot notation though:
collection.update({
_id: 1
}, {
$set: {
"foo.bar.apples": 4,
"foo.bar.bananas": 5
},
$currentDate: {
"foo.time": {
$type: 'timestamp'
}
}
}, function (err) {
console.log(err.name, err.message);
});
or just change MyObject to set this.time = new Date() instead of using $currentDate.

Resources