Mongodb 匹配条件和数组中的最新日期
上面是user1和user2之间的mongodb集合存储聊天。 我正在寻找一个查询,将给我的最新消息,其中的结果 message.sender=每行1个 i、 e寻找3行作为输出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" : [ {
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" } }