Mongodb 匹配条件和数组中的最新日期

Mongodb 匹配条件和数组中的最新日期,mongodb,aggregation-framework,Mongodb,Aggregation Framework,上面是user1和user2之间的mongodb集合存储聊天。 我正在寻找一个查询,将给我的最新消息,其中的结果 message.sender=每行1个 i、 e寻找3行作为输出 db.chat.find().pretty().limit(3) { "_id" : ObjectId("593921425ccc8150f35e7662"), "user1" : 1, "user2" : 2, "messages" : [ {

上面是user1和user2之间的mongodb集合存储聊天。 我正在寻找一个查询,将给我的最新消息,其中的结果 message.sender=每行1个

i、 e寻找3行作为输出

db.chat.find().pretty().limit(3)
{
    "_id" : ObjectId("593921425ccc8150f35e7662"),
    "user1" : 1,
    "user2" : 2,
    "messages" : [
        {
            "sender" : 1,
            "datetime" : ISODate("2017-06-08T10:04:50Z"),
            "body" : "hiii 0"
        },
        {
            "sender" : 2,
            "datetime" : ISODate("2017-06-09T10:04:50Z"),
            "body" : "hiii 1"
        },
        {
            "sender" : 2,
            "datetime" : ISODate("2017-06-10T10:04:50Z"),
            "body" : "hiii 2"
        }
    ]
}
{
    "_id" : ObjectId("593921425ccc8150f35e7663"),
    "user1" : 1,
    "user2" : 3,
    "messages" : [
        {
            "sender" : 1,
            "datetime" : ISODate("2017-06-08T10:04:50Z"),
            "body" : "hiii 0"
        },
        {
            "sender" : 3,
            "datetime" : ISODate("2017-06-09T10:04:50Z"),
            "body" : "hiii 1"
        },
        {
            "sender" : 1,
            "datetime" : ISODate("2017-06-10T10:04:50Z"),
            "body" : "hiii 2"
        }
    ]
}
{
    "_id" : ObjectId("593921425ccc8150f35e7664"),
    "user1" : 1,
    "user2" : 4,
    "messages" : [
        {
            "sender" : 1,
            "datetime" : ISODate("2017-06-08T10:04:50Z"),
            "body" : "hiii 0"
        },
        {
            "sender" : 1,
            "datetime" : ISODate("2017-06-09T10:04:50Z"),
            "body" : "hiii 1"
        },
        {
            "sender" : 4,
            "datetime" : ISODate("2017-06-10T10:04:50Z"),
            "body" : "hiii 2"
        }
    ]
}
就三排

db.chat.find({“messages.sender”:1})
给出了所有的行,而我只查找具有最新日期时间的匹配行。 请帮忙

例如:

For user1=1 and user2, message hiii0 should only come
For user1=1 and user3, message hiii2 should only come
For user1=1 and user4, message hiii1 should only come
是否将输出作为

db.chat.aggregate([
  {$unwind:"$messages"},
  {$match:{"messages.sender":1}},
  {$sort:{"messages.datetime":-1}
])
最后两行是不可取的,因为它不是user1-user2记录的最新记录


如果我添加,{$limit:1},它只给出一行。

这里的基本概念是,您需要聚合框架,以便应用条件来“过滤”条件中的数组元素。根据可用的版本,可以应用不同的技术

在所有情况下,这都是结果:

{
“_id”:ObjectId(“593921425ccc8150f35e7664”),
“用户1”:1,
“用户2”:4,
“信息”:{
“发送者”:1,
“日期时间”:ISODate(“2017-06-09T10:04:50Z”),
“正文”:“hiii 1”
}
}
{
“_id”:ObjectId(“593921425ccc8150f35e7663”),
“用户1”:1,
“用户2”:3,
“信息”:{
“发送者”:1,
“日期时间”:ISODate(“2017-06-10T10:04:50Z”),
“正文”:“hiii 2”
}
}
{
“_id”:ObjectId(“593921425ccc8150f35e7662”),
“用户1”:1,
“用户2”:2,
“信息”:{
“发送者”:1,
“日期时间”:ISODate(“2017-06-08T10:04:50Z”),
“正文”:“hiii 0”
}
}
MongoDB 3.4及以上版本
db.chat.aggregate([
{“$match”:{“messages.sender”:1},
{“$replaceRoot”:{
“新根”:{
“$let”:{
“vars”:{
“信息”:{
“$filter”:{
“输入”:“$messages”,
“as”:“m”,
“cond”:{“$eq”:[“$$m.sender”,1]}
}
},
“maxDate”:{
“$max”:{
“$map”:{
“输入”:{
“$filter”:{
“输入”:“$messages”,
“as”:“m”,
“cond”:{“$eq”:[“$$m.sender”,1]}
}
},
“as”:“m”,
“在”:“$$m.datetime”
}
}
}
},
“在”:{
“\u id”:“$\u id”,
“user1”:“$user1”,
“user2”:“$user2”,
“信息”:{
“$arrayElemAt”:[
{“$filter”:{
“输入”:“$$messages”,
“as”:“m”,
“cond”:{“$eq”:[“$$m.datetime”,“$$maxDate”]}
}},
0
]
}    
}
}
}
}}
])
这是利用它的最有效的方法,它允许我们使用声明变量以在“替换”结构中使用。这里的主要优点是,这只需要“两个”管道阶段

为了匹配您在应用逻辑操作测试
“sender”
的值时使用的数组内容。如果条件匹配,则只返回匹配的数组项

使用相同的方法,以便只考虑匹配的“发件人”条目,然后我们希望在“筛选”列表上应用于
“datetime”
中的值。
$max
]值是条件下的“最新”日期

我们需要这个值,以便以后可以将“筛选”数组返回的结果与这个“maxDate”进行比较。这是在“块中的“
”中发生的情况,在该块中,先前为过滤内容声明的两个“变量”和“maxDate”再次应用,以返回同时满足“最新日期”这两个条件的唯一值

因为您只需要“一”个结果,所以我们使用值而不是数组

MongoDB 3.2
db.chat.aggregate([
{“$match”:{“messages.sender”:1},
{“$project”:{
“用户1”:1,
“用户2”:1,
“信息”:{
“$filter”:{
“输入”:“$messages”,
“as”:“m”,
“cond”:{“$eq”:[“$$m.sender”,1]}
}
},
“maxDate”:{
“$max”:{
“$map”:{
“输入”:{
“$filter”:{
“输入”:“$messages”,
“as”:“m”,
“cond”:{“$eq”:[“$$m.sender”,1]}
}
},
“as”:“m”,
“在”:“$$m.datetime”
}
}
}         
}},
{“$project”:{
“用户1”:1,
“用户2”:1,
“信息”:{
“$arrayElemAt”:[
{“$filter”:{
“输入”:“$messages”,
“as”:“m”,
“cond”:{“$eq”:[“$$m.datetime”,“$maxDate”]}
}},
0
]
}
}}
])
这与描述的过程基本相同,但如果没有管道阶段,我们需要分两个阶段应用。这样做的原因是,我们需要“maxDate”中的“计算值”来完成最终操作,而在复合语句中无法完成此操作,因此我们拆分管道。这对运营的总体成本影响很小

在MongoDB 2.6到3.0中,我们可以使用这里的大部分技术,除了接受单个条目的“数组”结果,或者进入一个阶段来处理现在应该是单个条目的内容

MongoDB早期版本
db.chat.aggregate([
{“$match”:{“messages.sender”:1},
{“$unwind”:“$messages”},
{“$match”:{“messages.sender”:1},
{“$sort”:{“_id”:1,“messages.datetime”:-1},
{“$组”:{
“\u id”:“$\u id”,
“user1”:{“$first”:“$user1”},
“user2”:{“$first”:“$user2”},
“消息”:{“$first”:“$messages”}
}}
])
虽然看起来很简单,但这是迄今为止最昂贵的操作。这里必须使用,以便将条件应用于数组元素。这是一个非常昂贵的过程,因为它会产生
{ "_id" : ObjectId("593921425ccc8150f35e7663"), "user1" : 1, "user2" : 3, "messages" : { "sender" : 1, "datetime" : ISODate("2017-06-10T10:04:50Z"), "body" : "hiii 2" } }
{ "_id" : ObjectId("593921425ccc8150f35e7664"), "user1" : 1, "user2" : 4, "messages" : { "sender" : 1, "datetime" : ISODate("2017-06-09T10:04:50Z"), "body" : "hiii 1" } }
{ "_id" : ObjectId("593921425ccc8150f35e7662"), "user1" : 1, "user2" : 2, "messages" : { "sender" : 1, "datetime" : ISODate("2017-06-08T10:04:50Z"), "body" : "hiii 0" } }
{ "_id" : ObjectId("593921425ccc8150f35e7663"), "user1" : 1, "user2" : 3, "messages" : { "sender" : 1, "datetime" : ISODate("2017-06-08T10:04:50Z"), "body" : "hiii 0" } }
{ "_id" : ObjectId("593921425ccc8150f35e7664"), "user1" : 1, "user2" : 4, "messages" : { "sender" : 1, "datetime" : ISODate("2017-06-08T10:04:50Z"), "body" : "hiii 0" } }