Reputation: 686
I am using mongoose and have the following structure the documents:
{
user: {
comments: [
{ title: "mpla", active: true },
{ title: "mpla", active: false }
]
}
}
...
How can i return all my documents, but only the active comments in the comments array.
Upvotes: 1
Views: 130
Reputation: 3529
Taking a general case here where main documents may have others fields other than user
and user doc itself may have other fields as well:
Sample docs:
[
{
user: {
comments: [
{ title: "mpla", active: true },
{ title: "mpla", active: false }
],
name: "abc",
gender: "male",
createdDate: new Date("2019-04-01"),
modifiedDate: new Date("2019-08-24")
},
story: {
name: "a mocking bird",
year: 1994,
cost: "$5"
}
},
{
user: {
comments: [
{ title: "nope", active: true },
{ title: "hello", active: true }
],
name: "pqr",
gender: "female",
createdDate: new Date("2019-05-01"),
modifiedDate: new Date("2019-09-24")
},
story: {
name: "a kite runner",
year: 2005,
cost: "$2"
}
}
]
Now here all fields with documents must be returned but comments array should contain active=true
docs only.
Aggregation query with $filter and $project :
db.collection.aggregate([
{
$project: {
_id: 1,
story: 1,
user: {
name: 1,
gender: 1,
createdDate: 1,
modifiedDate: 1,
comments: {
$filter: {
input: "$user.comments",
as: "comment",
cond: { $eq: ["$$comment.active", true] }
}
}
}
}
}
]).pretty();
Output documents:
{
"_id" : ObjectId("5d8bb8c66926e92a334275d4"),
"user" : {
"name" : "abc",
"gender" : "male",
"createdDate" : ISODate("2019-04-01T00:00:00Z"),
"modifiedDate" : ISODate("2019-08-24T00:00:00Z"),
"comments" : [
{
"title" : "mpla",
"active" : true
}
]
},
"story" : {
"name" : "a mocking bird",
"year" : 1994,
"cost" : "$5"
}
},
{
"_id" : ObjectId("5d8bb8c66926e92a334275d5"),
"user" : {
"name" : "pqr",
"gender" : "female",
"createdDate" : ISODate("2019-05-01T00:00:00Z"),
"modifiedDate" : ISODate("2019-09-24T00:00:00Z"),
"comments" : [
{
"title" : "nope",
"active" : true
},
{
"title" : "hello",
"active" : true
}
]
},
"story" : {
"name" : "a kite runner",
"year" : 2005,
"cost" : "$2"
}
}
Upvotes: 1
Reputation: 463
You will have to use mongodb aggregation, so the query will be:
db.collectionName.aggregate(
{
$unwind: $user.comments
}
)
This will decontruct the comments array and will include other fields like the id included in each document. So e.g lets say your document was:
{ "_id": 1, "user" :
{ "comments":
[ { "title": "mpla", "active" : true }, { "title": "mpla", "active" : false } }]
}
}
Once we run the above given query it will result in the following documents:
{ "_id": 1, "user" :
{ "comments": { "title": "mpla", "active" : true }
}
}
}
{ "_id": 1, "user" :
{ "comments": { "title": "mpla", "active" : false }
}
}
}
As you can see now we have two separate documents you can now query them using $match operator and group them back into an array using $group operator. Hope that answers your question.
Upvotes: 1