Here is the structure of the document.
{
"_id" : ObjectId("5548f1cc0dcd6bd925a71ae2"), //document id
"messages" : [
{
"subject" : "NEW ++ SUBJECT",
"from" : ObjectId("5534b2992a104ed914435c31"),
"_id" : ObjectId("5548f1cc0dcd6bd925a71ae3"),
"created" : ISODate("2015-05-05T16:37:32.832Z"),
"read" : false,
"message" : "FIRST MESSAGE",
"participants" : [
ObjectId("5534b2992a104ed914435c31"),
ObjectId("5530af38576214dd3553331c")
]
},
{
"subject" : "dfgsd",
"from" : ObjectId("5534b2992a104ed914435c98"),//logged In USer
"_id" : ObjectId("5548f1df0dcd6bd925a71ae4"),
"created" : ISODate("2015-05-05T16:37:51.455Z"),
"read" : false,
"message" : "rdfgdgfd",
"participants" : [
ObjectId("5534b2992a104ed914435c98"),//logged In USer
ObjectId("5530af38576214dd3553331c")
]
}
"participants" : [
ObjectId("5534b2992a104ed914435c98"),//logged In USer
ObjectId("5534b2992a104ed914435c31"),
ObjectId("5530af38576214dd3553331c")
],
"__v" : 3
}
I want to get the message objects of the messages array whose 'read' value is 'false' & 'from' is NOT EQUAL TO LOGGED IN USER ( here logged in user is 5534b2992a104ed914435c98). And the 'participants' array of the document has to contain logged in user id(5534b2992a104ed914435c98). Here is the query I tried.
db.conversations.find({participants:ObjectId('5534b2992a104ed914435c98'),'messages.read':false,'messages.from':{$ne:ObjectId('5534b2992a104ed914435c98')}}).pretty().
Basically I am trying to get the count of unread messages. I am very new to mongodb/mongoose. Please correct me if you find something wrong in the question.
If you are trying to get the number of unread messages based on the criteria that the messages array whose 'read' value is 'false' & 'from' is NOT EQUAL TO LOGGED IN USER (here logged in user is 5534b2992a104ed914435c98
) and the 'participants'
array of the document has to contain logged in user id 5534b2992a104ed914435c98
, then the aggregation framework approach should help you to get the desired result.
The aggregation pipeline should have the first pipeline stage a $match
query which satisfies the above. This filters the documents that are necessary to be processed further down the pipeline stream.
The next pipeline stage after the $match
is the $unwind
operation which is done to deconstruct the messages
array so that you can output a document for each element.
A further filtering using $match
operator is required on the deconstructed messages to allow only those messages which meet the earlier criteria to be processed further down the pipeline.
This piece of operation is necessary for the next pipeline stage, the $group
operator which groups the incoming documents by a specified identifier expression and applies the $sum
accumulator expression to each group so that you can get the total number of documents in the group.
The last stage uses the $project
operator to reshape the final result document in the stream by suppressing the _id field and adds a new field unread_messages
that depicts the total number of messages with the read
field value as false.
The final aggregation pipeline would look like this:
var pipeline = [
{
"$match": {
"participants": ObjectId("5534b2992a104ed914435c98"),
"messages.read" : false,
"messages.from" : { "$ne": ObjectId('5534b2992a104ed914435c98') }
}
},
{
"$unwind": "$messages"
},
{
"$match": {
"participants": ObjectId("5534b2992a104ed914435c98"),
"messages.read" : false,
"messages.from" : { "$ne": ObjectId('5534b2992a104ed914435c98') }
}
},
{
"$group": {
"_id": null,
"count": {
"$sum": 1
}
}
},
{
"$project": {
"_id": 0,
"unread_messages": "$count"
}
}
]
You can use this in your Mongoose aggregation as follows:
Conversations.aggregate(pipeline, function (err, res) {
if (err) return handleError(err);
console.log(res); // [ { unread_messages: 34 } ] <-- this is a made up value :-)
});)
Or using the aggregation pipeline builder:
Conversations.aggregate()
.match({
"participants": ObjectId("5534b2992a104ed914435c98"),
"messages.read" : false,
"messages.from" : { "$ne": ObjectId('5534b2992a104ed914435c98') }
})
.unwind("messages")
.match({
"participants": ObjectId("5534b2992a104ed914435c98"),
"messages.read" : false,
"messages.from" : { "$ne": ObjectId('5534b2992a104ed914435c98') }
})
.group({ "_id": null, "unread_messages": { "$sum": 1 } })
.select("-id unread_messages")
.exec(function (err, res) {
if (err) return handleError(err);
console.log(res); // [ { unread_messages: 34 } ] <-- this is a made up value :-)
});