如何在mongoose / mongodb中使用不等于运算符?

时间:2015-05-05 16:55:55

标签: node.js mongodb mongoose

这是文件的结构。

{
    "_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

}

我想得到其“读取”值为“false”的消息数组的消息对象& 'from'不等于用户登录(此处登录用户为5534b2992a104ed914435c98)。并且文档的'参与者'数组必须包含登录的用户ID(5534b2992a104ed914435c98)。这是我试过的查询。

db.conversations.find({participants:ObjectId('5534b2992a104ed914435c98'),'messag‌​es.read':false,'messages.from':{$ne:ObjectId('5534b2992a104ed914435c98')}}).prett‌​y().

基本上我正在尝试获取未读消息的数量。 我是mongodb / mongoose的新手。如果您在问题中发现错误,请纠正我。

1 个答案:

答案 0 :(得分:8)

如果您尝试根据“读取”消息数组的条件获取未读消息的数量。价值是“假”' &安培; '从'不等于用户登录(此处登录用户为5534b2992a104ed914435c98)且文档的'participants'数组必须包含登录用户ID 5534b2992a104ed914435c98,然后 {{ 3}} 方法应该可以帮助您获得所需的结果。

聚合管道应该具有满足上述要求的第一个管道阶段aggregation framework查询。这会过滤需要在管道流中进一步处理的文档。

对于在处理之前不使用$match运算符首先展平消息数组的解决方案,请考虑 $unwind $filter <运营商如下:

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)

如果您使用的是不支持上述运算符的驱动程序,请考虑在$size作为$match操作后执行下一个管道阶段,以解构messages数组这样您就可以为每个元素输出文档。

在解构消息上需要使用$unwind运算符进行进一步过滤,以便只允许那些符合早期条件的消息在管道中进一步处理。

这一操作对于下一个管道阶段是必需的,$match运算符按指定的标识符表达式对传入文档进行分组,并将$group累加器表达式应用于每个组,以便您可以获得组中的文档总数。

最后一个阶段使用$sum运算符通过抑制_id字段来重新整形流中的最终结果文档,并添加一个新字段unread_messages,用于描述{{1}的消息总数字段值为false。

最终聚合管道如下所示:

read

您可以在Mongoose聚合中使用它,如下所示:

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"
        }

    }
]

或使用聚合管道构建器:

Conversations.aggregate(pipeline, function (err, res) {
    if (err) return handleError(err);
    console.log(res); // [ { unread_messages: 34 } ] <-- this is a made up value :-)
});)