参考问题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"
}
]
}
答案 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
,因为我刚刚阅读了有关按日期排序的需求的评论