假设我有一个看起来像这样的集合:
[{
_id: new ObjectId(),
type: 'foo',
value: 123,
date: '2022-06-30',
}, {
_id: new ObjectId(),
type: 'bar',
value: 321,
date: '2022-06-29',
}, {
_id: new ObjectId(),
type: 'foo',
value: 456,
date: '2022-06-28',
}, {
_id: new ObjectId(),
type: 'bar',
value: 789,
date: '2022-06-27',
}, {
_id: new ObjectId(),
type: 'baz',
value: 234,
date: '2022-06-26',
},
// etc....
]
按日期排序。
我想获得前两种类型中出现的所有最前面的项。在本例中,这意味着我想获得显示的最后一项上面的所有内容,该项类型为"baz",是在"foo"类型之后存在的第三种类型。和"bar".
// Expected result
[{
_id: new ObjectId(),
type: 'foo',
value: 123,
date: '2022-06-30',
}, {
_id: new ObjectId(),
type: 'bar',
value: 321,
date: '2022-06-29',
}, {
_id: new ObjectId(),
type: 'foo',
value: 456,
date: '2022-06-28',
}, {
_id: new ObjectId(),
type: 'bar',
value: 789,
date: '2022-06-27',
}]
假设这个新项被添加到集合中:
{
_id: new ObjectId(),
type: 'baz',
value: 567,
date: '2022-07-01',
}
新的预期结果将是
[{
_id: new ObjectId(),
type: 'baz',
value: 567,
date: '2022-07-01',
}, {
_id: new ObjectId(),
type: 'foo',
value: 123,
date: '2022-06-30',
}]
…作为"bar"from2022-06-29
现在是第三个出现在有序集中的类型。
从mongoDB版本5.0开始,您可以使用$setWindowFields
:
$setWindowFields
允许根据date
进行排序,并为每个文档添加一个新字段,其中包含一组type
s"到目前为止"。- 现在我们只需要匹配少于3个
topTypes
的文档。
db.collection.aggregate([
{
$setWindowFields: {
sortBy: {date: -1},
output: {
topTypes: {
$addToSet: "$type",
window: {documents: ["unbounded", "current"]}
}
}
}
},
{
$match: {$expr: {$lt: [{$size: "$topTypes"}, 3]}}
},
{
$unset: "topTypes"
}
])
看看它在操场的例子中是如何工作的