我有一个名为“Users”的 mongodb 集合,我想创建一个查询以基于名为
InsertedAt
的日期时间字段从该集合中获取第一个和最后一个文档。
我知道如何使用 sort
获取第一个和最后一个元素,但我想在一个查询中返回两条记录,如下所示:
[
{
_id: ObjectId("65c656fd8651a89640db013a"),
insertedAt: ISODate("2023-02-01T16:46:33.166Z"), // First record of collection
name: "Bob Jhonson"
},
{
_id: ObjectId("65c4d88a2a06618ad4e972f4"),
insertedAt: ISODate("2023-03-11T12:16:33.166Z"), // Last record of collection
name: "Bob Jhonson"
}
]
我该怎么做?
只需使用
$unionWith
将您的 2 个查询链接起来即可
db.collection.aggregate([
{
"$sort": {
"insertedAt": 1
}
},
{
$limit: 1
},
{
"$unionWith": {
"coll": "collection",
"pipeline": [
{
"$sort": {
"insertedAt": -1
}
},
{
$limit: 1
}
]
}
}
])
响应并不完全符合您想要的格式,但您可以仅使用一个
sort
和 group
阶段
测试一下这里
db.collection.aggregate([
{
"$sort": {
"InsertedAt": 1
}
},
{
"$group": {
"_id": null,
"first": {
"$first": "$$ROOT"
},
"last": {
"$last": "$$ROOT"
}
}
},
{
"$project": {
_id: 0
}
}
])
您可以使用这个:
$sort
- 按您想要的顺序排序。$facet
- 在 $sort
之后执行此阶段,如果 COLLSCAN
使用了 $sort
字段上的索引,则不会执行 insertedAt
。它将把你的集合变成一个名为 docs
的单个数组。$project
docs
数组中的第一个和最后一个元素。$unwind
将 docs
数组分成两个文档。$replaceWith
- 将结果的根设置为展开 docs
。db.collection.aggregate([
{
$sort: {
"insertedAt": 1
}
},
{
$facet: {
docs: []
}
},
{
$project: {
docs: [
{
$arrayElemAt: [
"$docs",
0
]
},
{
$arrayElemAt: [
"$docs",
-1
]
}
]
}
},
{
$unwind: "$docs"
},
{
$replaceWith: "$docs"
}
])
请参阅此处了解工作示例。