我正在尝试根据最新子文档的条件找出查询文档的最佳方法。
所以我的数据可能如下所示:
[{
_id: '59bb31efae69726bd5fc9391',
name: 'Something',
terms: [
{
_id: '58e54f5aad59a6000cdcd590',
begDate: '2017-06-13T07:00:00.000Z',
endDate: '2018-01-01T07:59:59.999Z'
},
{
_id: '59bb32765e651d28909ed706',
begDate: '2018-01-01T08:00:00.000Z',
endDate: '2019-01-01T07:59:59.999Z'
}
]
}, {
_id: '59f20ddeef426f6bca3abbf1',
name: 'Something',
terms: [
{
_id: '59f20e35c8257b5b0f22d2a6',
begDate: '2018-06-13T07:00:00.000Z',
endDate: '2019-01-01T07:59:59.999Z'
},
{
_id: '59f20e9394c8108d9db33bf9',
begDate: '2019-01-01T08:00:00.000Z',
endDate: '2020-01-01T07:59:59.999Z'
}
]
}]
我想要的是获取 上一学期 endDate
为2019-01-01T07:59:59.999Z
的所有文件{
_id: {
'$in': [
ObjectId("591e5e37abddad14afe1b272"),
ObjectId("591e5e37abddad14afe1b123")
]
}
}
这可以通过获取最后一个字词来完成一个数组,或者更可靠地排序术语,然后抓住最后一个。
我可以看到我如何用$where做到这一点,但我知道如果我能找到另一种更高效的方式。
我也想添加,无论我在这里做什么都会伴随其他查询参数。例如:
P5
更新
如上所述,这个问题有重复(我很难找到,因为引用的问题很难理解)。话虽这么说,我不仅在寻找阵列中的最后一个,而且也是最近的(我同意在问题正文中不清楚)。我不反对重复的问题参考,但是为了使未来的读者更容易,你会在接受的答案中找到mongo 3.6+的一个干净的解决方案,以及对评论中另一个问题的参考。如果您想在子文档中按日期查询 ,应该会有所帮助。
答案 0 :(得分:1)
使用$expr
执行“复杂”匹配,使用$let
使用中间变量存储使用"$arrayElemAt": [ "$terms", -1 ]
找到的数组的最后一个元素,以便将其与相关日期进行比较:
db.collection.find({
$expr: {
$let: {
vars: { "last": { $arrayElemAt: [ "$terms", -1 ] } },
in: { $eq: [ "$$last.endDate", "2019-01-01T07:59:59.999Z" ] }
}
}
})
返回您提供第一条记录的输入。
并且,根据您的要求,为了不排除添加其他过滤器的可能性,您可以使用$and
添加它们:
db.collection.find({
$and: [
{ $expr: { $let: {
vars: { "last": { $arrayElemAt: [ "$terms", -1 ] } },
in: { $eq: [ "$$last.endDate", "2019-01-01T07:59:59.999Z" ] }
}}},
{ "_id": { $ne: "sss" } } // actually whatever additional filter
]
})
如果您希望使用匹配的文档执行其他阶段,可以使用aggregate
管道实现完全相同的事情:
db.collection.aggregate([
{ $match: {
$and: [
{ $expr: { $let: {
vars: { "last": { $arrayElemAt: [ "$terms", -1 ] } },
in: { $eq: [ "$$last.endDate", "2019-01-01T07:59:59.999Z" ] }
}}},
{ "_id": { $ne: "sss" } }
]
}},
{ ... }
])