Sac*_*lsi 0 mongoose mongodb node.js
这是文档的结构.
{
"_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
}
Run Code Online (Sandbox Code Playgroud)
我想得到消息数组的消息对象,其'read'值为'false'且'from'不等于用户登录(此处登录用户为5534b2992a104ed914435c98).并且文档的'参与者'数组必须包含登录的用户ID(5534b2992a104ed914435c98).这是我试过的查询.
db.conversations.find({participants:ObjectId('5534b2992a104ed914435c98'),'messag??es.read':false,'messages.from':{$ne:ObjectId('5534b2992a104ed914435c98')}}).prett??y().
Run Code Online (Sandbox Code Playgroud)
基本上我试图得到未读消息的计数.我是mongodb/mongoose的新手.如果您在问题中发现错误,请纠正我.
如果您尝试根据条件来获取未读消息的数量,那么"读取"值为"false"和"from"的消息数组不等于用户登录(此处登录用户为5534b2992a104ed914435c98)且'participants'数组为文档必须包含登录的用户ID 5534b2992a104ed914435c98,然后聚合框架方法应该可以帮助您获得所需的结果.
聚合管道应该使第一个管道阶段具有$match满足上述要求的查询.这会过滤需要在管道流中进一步处理的文档.
对于$unwind在处理之前不使用运算符首先展平消息数组的解决方案,请考虑$filter和$size运算符,如下所示:
var pipeline = [
{
"$match": {
"participants": ObjectId("5534b2992a104ed914435c98"),
"messages.read" : false,
"messages.from" : { "$ne": ObjectId('5534b2992a104ed914435c98') }
}
},
{
"$project": {
"_id": 0,
"unread_messages": {
"$size": {
"$filter": {
"input": "$messages",
"as": "msg",
"cond": {
"$and": [
{ "$not": [ "$$msg.read" ] },
{ "$ne": ["$$msg.from", ObjectId('5534b2992a104ed914435c98')]}
]
}
}
}
}
}
}
]
db.conversations.aggregate(pipeline)
Run Code Online (Sandbox Code Playgroud)
如果您使用的是不支持上述运营商的驱动程序,请考虑之后的下一个流水线级$match作为$unwind其完成解构操作messages数组,这样就可以输出文档的每个元素.
$match在解构消息上需要使用运算符进一步过滤,以仅允许那些满足早期标准的消息在管道中进一步处理.
这个操作对于下一个管道阶段是必需的,$group操作员通过指定的标识符表达式对传入文档进行分组,并将$sum累加器表达式应用于每个组,以便您可以获得组中的文档总数.
最后一个阶段使用$project运算符通过抑制_id字段来重新整形流中的最终结果文档,并添加一个新字段unread_messages,该字段描述read字段值为false 的消息总数.
最终的聚合管道如下所示:
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"
}
}
]
Run Code Online (Sandbox Code Playgroud)
您可以在Mongoose聚合中使用它,如下所示:
Conversations.aggregate(pipeline, function (err, res) {
if (err) return handleError(err);
console.log(res); // [ { unread_messages: 34 } ] <-- this is a made up value :-)
});)
Run Code Online (Sandbox Code Playgroud)
或者使用聚合管道构建器:
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 :-)
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
12634 次 |
| 最近记录: |