$ MongoDB在某些条件下查找并获取计数

时间:2018-01-20 04:49:05

标签: mongodb mongodb-query aggregation-framework

有2个用于处理聊天的集合

  1. 适用于聊天室
  2. 用于聊天消息
  3. chatRooms的示例数据如下

    {
     "data": [
        {
            "_id": "5a606ab0116e2c164b25ef33",
            "topic": "akhil Ben chat",
            "topicDesc": "question 1",
            "roomName": "benakhil777akhil",
            "createdOn": "2018-01-18T09:36:48.231Z",
            "participants": [
                "ben",
                "akhil777"
            ],
            "__v": 0
        },
        {
            "_id": "5a4dbdaab46b426863e7ead3",
            "topic": "test",
            "topicDesc": "test123",
            "roomName": "benakhil777test",
            "createdOn": "2018-01-04T05:37:46.088Z",
            "participants": [
                "ben",
                "akhil777"
            ],
            "__v": 0
        }
    ]}
    

    chatMessages的示例数据如下

    {"data": [
    
        {
            "_id": "5a62281ea0652120a6668bae",
            "topic": "akhil Ben chat",
            "roomName": "benakhil777akhil",
            "message": "test 1",
            "__v": 0,
            "readStatus": [
                {
                    "recipient": "ben",
                    "_id": "5a62281ea0652120a6668bb0",
                    "status": true
                },
                {
                    "recipient": "akhil777",
                    "_id": "5a62281ea0652120a6668baf",
                    "status": true
                }
            ],
            "createdOn": "2018-01-19T17:17:18.456Z"
        },
        {
            "_id": "5a622866a0652120a6668bb1",
            "topic": "akhil Ben chat",
            "roomName": "benakhil777akhil",
            "message": "Test 2",
            "__v": 0,
            "readStatus": [
                {
                    "recipient": "ben",
                    "_id": "5a622866a0652120a6668bb3",
                    "status": false
                },
                {
                    "recipient": "akhil777",
                    "_id": "5a622866a0652120a6668bb2",
                    "status": true
                }
            ],
            "createdOn": "2018-01-19T17:18:30.396Z"
        },
        {
            "_id": "5a62287ca0652120a6668bb4",
            "topic": "akhil Ben chat",
            "roomName": "benakhil777akhil",
            "message": "test 3",
            "__v": 0,
            "readStatus": [
                {
                    "recipient": "ben",
                    "_id": "5a62287ca0652120a6668bb6",
                    "status": false
                },
                {
                    "recipient": "akhil777",
                    "_id": "5a62287ca0652120a6668bb5",
                    "status": true
                }
            ],
            "createdOn": "2018-01-19T17:18:52.018Z"
        }
    ]}
    

    在上面的JSON readStatus存储状态中,用户是否读取了消息。这样我就可以为每个聊天室计算用户的未读消息。 readStatus中的状态保存消息的读取状态,读取消息时为true。 有两个房间 benakhil777akhil benakhil777test

    我想得到的是用户说每个房间的未读消息数 ben

    还有userDetails集合 比方说,

     [{
       "_id": "59e6d6ba02e11e1814481022",
       "username": "ben",
       "name": "Ben S",
       "email": "qwerty@123.com",
    },{
       "_id": "59e6d6ba02e11e1814481022",
       "username": "akhil777",
       "name": "Akhil Clement",
       "email": "qwerty@123.com",
    }]
    

    这将是用户详细信息集合

    并输出我需要的JSON就像。

    {
     "data": [
        {
            "_id": "5a606ab0116e2c164b25ef33",
            "topic": "akhil Ben chat",
            "topicDesc": "question 1",
            "roomName": "benakhil777akhil",
            "createdOn": "2018-01-18T09:36:48.231Z",
            "participants": [
                "ben",
                "akhil777"
            ],
            "participantDetails":[{
                       "_id": "59e6d6ba02e11e1814481022",
                       "username": "ben",
                       "name": "Ben S",
                       "email": "qwerty@123.com",
                     },{
                       "_id": "59e6d6ba02e11e1814481022",
                       "username": "akhil777",
                       "name": "Akhil Clement",
                       "email": "qwerty@123.com",
            }],
            "unreadCount": 2,
            "__v": 0
        },
        {
            "_id": "5a4dbdaab46b426863e7ead3",
            "topic": "test",
            "topicDesc": "test123",
            "roomName": "benakhil777test",
            "createdOn": "2018-01-04T05:37:46.088Z",
            "participants": [
                "ben",
                "akhil777"
            ],
            "participantDetails":[{
                       "_id": "59e6d6ba02e11e1814481022",
                       "username": "ben",
                       "name": "Ben S",
                       "email": "qwerty@123.com",
                     },{
                       "_id": "59e6d6ba02e11e1814481022",
                       "username": "akhil777",
                       "name": "Akhil Clement",
                       "email": "qwerty@123.com",
            }],
            "unreadCount": 0,
            "__v": 0
        }
    ]}
    

3 个答案:

答案 0 :(得分:1)

请尝试此聚合管道

db.rooms.aggregate(
    [
        {$match : {participants : 'ben'}},
        {$lookup : { 
            from : "chats", 
            localField : "roomName", 
            foreignField:"roomName",
            as :"out"
            }
        },
        {$unwind : {
                path: "$out",
                preserveNullAndEmptyArrays: true
            }
        },
        {$unwind : {
                path: "$out.readStatus",
                preserveNullAndEmptyArrays: true
            }
        },
        {$addFields : {
                isMatch : { $and : [
                    { $eq : ["$out.readStatus.recipient" , "ben" ] } , { $eq : [ "$out.readStatus.status" , false ] } ]
                }
            }
        },
        {$group : {
                _id : {
                    _id : "$_id" , 
                    topic : "$topic",
                    topicDesc : "$topicDesc",
                    createdOn : "$createdOn",
                    participants : "$participants",
                    roomName : "$roomName"
                },
                unreadCount : { $sum : { $cond : [ "$isMatch" , 1, 0 ]  } }
            }
        },
        {$sort : {unreadCount : -1}}
    ]
).pretty()

结果

{
    "_id" : {
        "_id" : "5a606ab0116e2c164b25ef33",
        "topic" : "akhil Ben chat",
        "topicDesc" : "question 1",
        "createdOn" : "2018-01-18T09:36:48.231Z",
        "participants" : [
            "ben",
            "akhil777"
        ],
        "roomName" : "benakhil777akhil"
    },
    "unreadCount" : 2
}
{
    "_id" : {
        "_id" : "5a4dbdaab46b426863e7ead3",
        "topic" : "test",
        "topicDesc" : "test123",
        "createdOn" : "2018-01-04T05:37:46.088Z",
        "participants" : [
            "ben",
            "akhil777"
        ],
        "roomName" : "benakhil777test"
    },
    "unreadCount" : 0
}

编辑,因为addFields在3.2.17

中不可用
{$group : {
                _id : {
                    _id : "$_id" , 
                    topic : "$topic",
                    topicDesc : "$topicDesc",
                    createdOn : "$createdOn",
                    participants : "$participants",
                    roomName : "$roomName"
                },
                unreadCount : { $sum : { $cond : [ { $and : [
                    { $eq : ["$out.readStatus.recipient" , "ben" ] } , { $eq : [ "$out.readStatus.status" , false ] } ]
                } , 1, 0 ]  } }
            }
        }

EDIT-2 添加了$project

    {$project : 
        { 
            "_id" : "$_id._id",
            "topic" : "$_id.topic",
            "topicDesc" : "$_id.topicDesc",
            "createdOn" : "$_id.createdOn",
            "participants" : "$_id.participants",
            "roomName" : "$_id.roomName",
            "unreadCount" : "$unreadCount"
        }
    }

答案 1 :(得分:1)

您可以简化代码以便在聚合下使用。

带有输入条件的

$cond用于检查读状态标志,当为真时输出1为0。

内部$sum使用外部$ sum计算每条聊天消息中的未读值,以便对所有匹配的聊天消息中的未读值进行求和。

db.chatRooms.aggregate(
[{
  "$match":{"participants":"ben"}},
  {"$lookup":{
    "from":"chatMessages",
    "localField":"roomName",
    "foreignField":"roomName",
    "as":"chatMessages"
  }},
  {"$project":{
    "topic":1,
    "topicDesc":1,
    "roomName":1,
    "createdOn":1,
    "participants":1,
    "unreadCount":{
      "$sum":{
        "$map":{
          "input":"$chatMessages",
          "as":"chatMessage",
          "in":{
            "$sum":{
              "$map":{
                "input":"$$chatMessage.readStatus",
                "as":"mChatMessage",
                "in":{"$cond":[{"$eq":["$$mChatMessage.status",false]},1,0]}
              }
            }
          }
        }
      }
    }
  }}
])

答案 2 :(得分:0)

结果JSON包含用户详细信息。

db.chatRooms.aggregate(
     [
                {$match : {participants : 'ben'}},
                { $unwind : {
                        path: "$participants",
                        preserveNullAndEmptyArrays: true
                    }
                },
                { $lookup: {
                    from:"users",
                    localField:"participants",
                    foreignField:"username",
                    as:"userData"
                    }
                },
                { $lookup: {
                    from:"chatmessages",
                    localField:"roomName",
                    foreignField:"roomName",
                    as:"out"
                    }
                },

                { $unwind : {
                        path: "$out",
                        preserveNullAndEmptyArrays: true
                    }
                },
                { $unwind : {
                        path: "$out.readStatus",
                        preserveNullAndEmptyArrays: true
                    }
                },
                { $group : {
                        _id : {
                            _id : "$_id" , 
                            topic : "$topic",
                            topicDesc : "$topicDesc",
                            createdOn : "$createdOn",
                            roomName : "$roomName"
                        },
                        participants : {$addToSet :  "$participants" } ,  
                        participantDetails : {$addToSet : {$arrayElemAt : ["$userData", 0]}},
                        unreadCount : {
                            $sum : { 
                                $cond : [ {
                                 $and : [
                                            { $eq : ["$out.readStatus.recipient" , "ben" ] } , 
                                            { $eq : [ "$out.readStatus.status" , false ] } 
                                        ]
                                    } , 1, 0 
                                    ]  
                                } 
                            }
                        }
                }
                ,
                { $project : 
                    { 
                        _id : "$_id._id",
                        topic : "$_id.topic",
                        topicDesc : "$_id.topicDesc",
                        createdOn : "$_id.createdOn",
                        participants : "$_id.participants",
                        roomName : "$_id.roomName",
                        unreadCount : "$unreadCount",
                        participants : 1 ,  
                        participantDetails : 1
                    }
                }

            ])