我们有一个集合,其中有多个文档按照给定的时间戳排序。我们希望聚合两个时间戳之间的文档(比如startTime和stopTime):这是我们聚合中一个简单的匹配阶段,它有一个类似于timestamp的查询:{$gte:开始时间,$lte:stopTime}。但是,我们希望在此步骤的结果中包含两个额外的文档:在startTime之前最接近的文档,无论我们需要查看的时间有多远,并且在stopTime之后最接近的文档。
qhhrdooz1#
如果你已经过滤掉这些文档,一个选择是使用一个$lookup步骤和一个管道。在$lookup之后看起来有点笨拙,但是我想不出另一种方法来继续,而不分组所有的文档,这不是最好的方法。
$lookup
$match
$set
before
after
$unwind
$group
_id
db.collection.aggregate([ {$match: {timestamp: {$gte: startTime, $lte: stopTime}}}, {$set: {data: "$$ROOT"}}, {$lookup: { from: "collection", let: {}, pipeline: [ {$match: {timestamp: {$lt: startTime}}}, {$sort: {timestamp: -1}}, {$limit: 1} ], as: "before" }}, {$lookup: { from: "collection", let: {}, pipeline: [ {$match: {timestamp: {$gt: stopTime}}}, {$sort: {timestamp: 1}}, {$limit: 1} ], as: "after" }}, {$project: {_id: 0, data: {$concatArrays: ["$after", "$before", ["$data"]]}}}, {$unwind: "$data"}, {$group: {_id: "$data._id", data: {$first: "$data"}}}, {$replaceRoot: {newRoot: "$data"}}, {$sort: {timestamp: 1}} ])
了解它在playground example上的工作原理
iqxoj9l92#
将$unionWith与$sort和$limit: 1链接起来,使文档超出范围。
$unionWith
$sort
$limit: 1
db.collection.aggregate([ { $match: { datetime: { $gte: ISODate("2022-10-18"), $lte: ISODate("2022-10-19") } } }, { "$unionWith": { "coll": "collection", "pipeline": [ { $match: { datetime: { $lt: ISODate("2022-10-18") } } }, { $sort: { datetime: -1 } }, { $limit: 1 } ] } }, { "$unionWith": { "coll": "collection", "pipeline": [ { $match: { datetime: { $gt: ISODate("2022-10-19") } } }, { $sort: { datetime: 1 } }, { $limit: 1 } ] } } ])
这里是Mongo Playground供您参考。
2条答案
按热度按时间qhhrdooz1#
如果你已经过滤掉这些文档,一个选择是使用一个
$lookup
步骤和一个管道。在$lookup
之后看起来有点笨拙,但是我想不出另一种方法来继续,而不分组所有的文档,这不是最好的方法。$match
-这是一个“假”的步骤,目的是与您的情况保持一致。您已经在当前的渠道中使用了它,因此在这里不需要它$set
“$$ROOT”以便以后使用$lookup
两次,以便从原始集合中获取您请求的文档1.为每个文档创建一个文档数组,以获取当前文档中的
before
和after
$unwind
以分隔成文件$group
与_id
,以便删除before
和after
文档的重复项1.格式Name
了解它在playground example上的工作原理
iqxoj9l92#
将
$unionWith
与$sort
和$limit: 1
链接起来,使文档超出范围。这里是Mongo Playground供您参考。