复杂的Mongo查询

时间:2017-06-23 12:52:35

标签: mongodb

参考问题Match conditions and latest date from array,其好的解决方案由Neil Lunn提供。

db.chat.find().pretty().limit(2)
{
    "_id" : ObjectId("593921425ccc8150f35e7662"),
    "user1" : 1,
    "user2" : 2,
    "messages" : [
        {
            "sender" : 1,
            "datetime" : ISODate("2017-05-01T00:00:00Z"),
            "body" : "hiii 120"
        },
        {
            "sender" : 1,
            "datetime" : ISODate("2017-06-01T00:00:00Z"),
            "body" : "hiii 121"
        },
        {
            "sender" : 2,
            "datetime" : ISODate("2017-06-10T00:00:00Z"),
            "body" : "hiii 2"
        }
    ]
}
{
    "_id" : ObjectId("593921425ccc8150f35e7663"),
    "user1" : 1,
    "user2" : 3,
    "messages" : [
        {
            "sender" : 1,
            "datetime" : ISODate("2017-05-02T00:00:00Z"),
            "body" : "hiii 130"
        },
        {
            "sender" : 1,
            "datetime" : ISODate("2017-06-02T00:00:00Z"),
            "body" : "hiii 131"
        },
        {
            "sender" : 3,
            "datetime" : ISODate("2017-06-10T00:00:00Z"),
            "body" : "hiii 2"
        }
    ]
}

这里的问题陈述是我需要用户列表,其中messages.sender = 1 by datetime desc。

即 输出:

    {
        "sender" : 1,
        "receiver" : 2,
        "datetime" : ISODate("2017-06-02T00:00:00Z"),
        "body" : "hiii 131"
    },
    {
        "sender" : 1,
        "receiver" : 2,
        "datetime" : ISODate("2017-06-01T00:00:00Z"),
        "body" : "hiii 121"
    },                      
    {
        "sender" : 1,
        "receiver" : 3,
        "datetime" : ISODate("2017-05-02T00:00:00Z"),
        "body" : "hiii 130"
    },
    {
        "sender" : 1,
        "receiver" : 3,
        "datetime" : ISODate("2017-05-01T00:00:00Z"),
        "body" : "hiii 120"
    },

尝试了很多查询,但无法获得所需的输出。

解释输出:

db.chat.find().pretty().limit(2)
{
    "_id" : ObjectId("593921425ccc8150f35e7662"),
    "user1" : 1,
    "user2" : 2,
    "messages" : [
        {
            "sender" : 1,
            **"datetime" : ISODate("2017-05-01T00:00:00Z"),**--- message will apear at No4 as sender=1. Also we need data of user1/user2 which is not equal to 1 i.e 2.
            "body" : "hiii 120"
        },
        {
            "sender" : 1,
            **"datetime" : ISODate("2017-06-01T00:00:00Z"),**--- message will apear at No2 as sender=1. Also we need data of user1/user2 which is not equal to 1 i.e 2.
            "body" : "hiii 121"
        },
        {
            "sender" : 2,
            "datetime" : ISODate("2017-06-10T00:00:00Z"),
            "body" : "hiii 2"
        }
    ]
}
{
    "_id" : ObjectId("593921425ccc8150f35e7663"),
    "user1" : 1,
    "user2" : 3,
    "messages" : [
        {
            "sender" : 1,
            **"datetime" : ISODate("2017-05-02T00:00:00Z"),** --- message will apear at No3 as sender=1. Also we need data of user1/user2 which is not equal to 1 i.e 3.
            "body" : "hiii 130"
        },
        {
            "sender" : 1,
            **"datetime" : ISODate("2017-06-02T00:00:00Z"),** --- message will apear at top as sender=1 and of max datetime. Also we need data of user1/user2 which is not equal to 1 i.e 3.
            "body" : "hiii 131"
        },
        {
            "sender" : 3,
            "datetime" : ISODate("2017-06-10T00:00:00Z"),
            "body" : "hiii 2"
        }
    ]
}

1 个答案:

答案 0 :(得分:1)

使用您提供的数据进行测试。这有效:

db.getCollection('test').aggregate([
{$unwind:"$messages"},
{$match : {"messages.sender" : 1}},
{$project:{
    "_id" : 0, 
    "sender" : "$messages.sender", 
    "datetime" : "$messages.datetime",
    "body" : "$messages.body",
    "receiver" : {$cond : {if: { $eq : ["$messages.sender","$user1"]}, then: "$user2", else: "$user1"}},
    }
},
{$sort : {"datetime" : 1}}
])

$unwind将为所有邮件创建一个单独的对象。

$match仅保留发件人= 1

的人

$project将数据转换为您请求的格式。

因为我们希望接收者是用户1或用户2,具体取决于发件人,我们需要$cond声明。

编辑: 添加$sort,因为我刚刚阅读了有关按日期排序的需求的评论