How to pull an object from array in MongoDB - javascript

I have pull friend request when it is accepted or canceled. So, when I try to pull it from array, it doesn't work.
It matches for 1 document but 0 document modified.
When I delete the requested_at field from user field, it works well.
Where do I make mistake at ?
MongoDB Document
{
"_id" : ObjectId("5cb18680aa024b2d441f93cc"),
"friends" : [],
"friend_requests" : [
{
"user" : {
"id" : ObjectId("5cb14fd7db537905c89e0a72"),
"requested_at" : ISODate("2019-04-14T17:51:00.588Z")
}
}
]
}
MongoDB Query
db.getCollection('users').updateOne(
{ _id: ObjectId("5cb18680aa024b2d441f93cc") },
{
$pull: {
friend_requests: {
user: {
id: ObjectId("5cb14fd7db537905c89e0a72")
}
}
}
});
Result
{
"acknowledged" : true,
"matchedCount" : 1.0,
"modifiedCount" : 0.0
}

Use dot notation to specify a condition:
db.users.updateOne(
{ _id: ObjectId("5cb18680aa024b2d441f93cc") },
{
$pull: {
"friend_requests": {
"user.id": ObjectId("5cb14fd7db537905c89e0a72")
}
}
});

Related

How to get array length instead of full array in find()?

I have a mongodb (using mongoose) collection ("items") which includes an array ("images") among its properties. Some example documents:
[
{
"_id" : ObjectId("543fa67e9672ec37ebe3d026"),
"name" : "Alice",
"images" : [
{ url: "http://images.com/1.jpg" },
{ url: "http://images.com/2.jpg" },
{ url: "http://images.com/3.jpg" },
]
},
{
"_id" : ObjectId("543fa67e9672ec37ebe3d027"),
"name" : "Bob",
"images" : [
{ url: "http://images.com/4.jpg" },
{ url: "http://images.com/5.jpg" },
]
},
]
I want to implement a query which returns - along with other document properties - the array length (and not the array contents). I know I can get the array length with
db.items.aggregate([
{ "$project" : { "_id" : 0, "imagesLength" : { "$size" : "$images" } } }
])
But I need the imagesLength values along with the documents returned with a find:
db.items.findMany(
{ ...filter },
{ name: 1, imagesCount: 1 }
);
The question is: how can I get the array length along with the find results ?
You can do same as aggregation projection in find's second argument,
Starting in MongoDB 4.4, as part of making find projection consistent with aggregation’s $project stage,
db.items.find(
{ ...filter },
{
_id: 0,
name: 1,
images: { $size: "$images" }
})
Playground
You can add a match stage at first in your aggregation to filter the results. Then you can project all fields needed and generate the new ones.
db.items.aggregate([
{ "$match" : { ...filter },
{ "$project" : { "imagesLength" : { "$size" : "$images" }, "name": 1 } }
])

Mongoose: insert object into a sub-document array

I am trying to insert a time object into the times array for a specific activity name for a specific user. For example, if the user was "someuser" and I wanted to add a time to the times for guitar I am unsure as to what to do.
{
username: "someuser",
activities: [
{
name: "guitar",
times: []
},
{
name: "code",
times: []
}
]
}, {
username: "anotheruser",
activities: []
}
This is currently the function that I have, I cannot figure out what I am doing wrong, any help would be greatly appreciated:
function appendActivityTime(user, activityName, newRange) {
User.updateOne(
{username: user, 'activities.name': activityName},
{ $push: {'activities.$.times': {newRange}},
function (err) {
if (err) {
console.log(err);
} else {
console.log("Successfully added time range: " + newRange);
}
}}
);
}
appendActivityTime("someuser", "guitar", rangeObject);
i've tried your attempt and it worked for me:
db.getCollection("test").updateOne(
{ username: "someuser", "activities.name": "guitar" },
{ $push: { "activities.$.times": { from: ISODate(), to: ISODate() } } } //Don't worry about ISODate() in node.js use date objects
)
results:
{
"_id" : ObjectId("5f6c384af49dcd4019982b2c"),
"username" : "someuser",
"activities" : [
{
"name" : "guitar",
"times" : [
{
"from" : ISODate("2020-09-24T06:15:03.578+0000"),
"to" : ISODate("2020-09-24T06:15:03.578+0000")
}
]
},
{
"name" : "code",
"times" : [
]
}
]
}
what i would suggest you using instead is arrayFilter, they are much more precise and when you get used to them, they became very handy
If you are not confident with updating nested documents, let mongoose make the query.
let document = await Model.findOne ({ });
document.activities = new_object;
await document.save();

mongodb pull object from an array not working using mongoose

I am trying to remove a comment object from an array in a mongodb using the $pull operator and it seems like I have the syntax correct but it is not modifying anything.
I have looked through all the examples given on Stack to make but it still keeps responding with
{ n: 0,
nModified: 0,
opTime:
{ ts:
Timestamp { _bsontype: 'Timestamp', low_: 1, high_: 1548664023 },
t: 1 },
electionId: 7fffffff0000000000000001,
ok: 1,
operationTime:
Timestamp { _bsontype: 'Timestamp', low_: 1, high_: 1548664023 },
'$clusterTime':
{ clusterTime:
Timestamp { _bsontype: 'Timestamp', low_: 1, high_: 1548664023 },
signature: { hash: [Binary], keyId: [Long] } } }
this is the field I currently have in the DB
{
"_id" : ObjectId("5be23d8aa365d853ddfd6f15"),
"__v" : 0,
"restaurant" : {
info about restaurant
},
"comments" : [
{
"id" : "61DSLu7fFcUZ2chA8-A6HQ",
"user" : "test",
"comment" : "test"
},
{
"comment" : "testing",
"user" : "testing",
"id" : ObjectId("5c3cd3a5647f180484a5ca18")
},
{
"restaurant_id" : "61DSLu7fFcUZ2chA8-A6HQ",
"comment" : "tacos",
"name" : "test",
"user_id" : ObjectId("5c48fdf47e9ed81b08536602")
},
{
"restaurant_id" : "61DSLu7fFcUZ2chA8-A6HQ",
"comment" : "tacos",
"name" : "test",
"comm_id" : ObjectId("5c49019f8528f31b2adfb914")
},
{
"restaurant_id" : "61DSLu7fFcUZ2chA8-A6HQ",
"comment" : "hello",
"name" : "test",
"comm_id" : ObjectId("5c490237fd6e781b52f801fe")
}
],
"likes" : {
"likes" : 6
}
Currently my model shows within my restaurants model
comments: [{
restaurant_id : String,
comment : String,
name : String,
comm_id : String,
}]
the update method I have currently
db.restaurants.updateOne({restaurant_id: rest_id},
{ $pull: { comments: { $in: [{comment: "hello"}] } }
}, { safe: true })
and also have tried
db.restaurants.updateOne({restaurant_id: rest_id},
{ $pull: { comments: { $in: {"comment": "hello"} } }
}, { safe: true })
as well as
db.restaurants.updateOne({restaurant_id: rest_id},
{ $pull: { comments: { comment: "hello"} } }
}, { safe: true })
and similar variation. I can't seem to pinpoint my mistake. the response seems like it is finding the correct restaurant field, but my $pull operator just isn't working properly. Is there something wrong with my syntax or does it not work in this scenario.
Ideally, I will use the comm_id field to remove the object from the array, but I am using comment: "hello" just to test.
Is it possibly because I have different fields in the first few comments?
do it simple it will works
db.restaurants.updateOne({restaurant_id: rest_id},
{ $pull: { comments.comment: "hello"} }
}, { safe: true })

Returning particular arrays from objects in mongodb

[
{
_id: 555,
names:['John','Doe','David']
},
{
_id: 625,
names:['David','Mark','Carl']
},
{
_id: 299,
names:['Bill','Carlos','Ventus']
}
]
How can I return only the names(object) of all the object having _id in MongoDB ?
Please help me..
model.find({_id : { $exists : 1} }, "-_id names", { lean : true })
As each document in mongoDB has _id : model.find({}, "-_id names", { lean : true }) this would be fine.
You could also use mongo aggregate as follows :
model.aggregate({ $project : { _id : 0, names : 1 })

mongoDB: remove empty objects in an object-array

Unfortunately I got some false objects in an array in some documents, which are structured like this:
{
"_id" : "8vJY4baMbdYkgHian",
"title" : "Cars",
"tradename" : [
{
},
{
"element" : "Audi"
},
{
"element" : "Mercedes"
}
]
}
As you can see in this example, the first object in the array is empty. How can I remove empty objects in all tradename-arrays of all documents in the collection?
Collection.update(
{ 'tradename': {} },
{ $pull: { 'tradename.$': '' } }
);
An alternative approach to remove empty objects from an array with no assumptions:
db.a.update(
{"tradename": {}},
{ $pull: { 'tradename': {$in:[{}]} } },
{ "multi": true }
);
The following update operation using $pull updates all documents in the collection to remove empty objects from the array tradename, given that the embedded document has the element property only:
db.collection.update(
{ },
{ "$pull": { "tradename": { "element": { "$exists": false } } } },
{ "multi": true }
)

Categories