我想返回节点中匹配对象 id 的上一个对象和下一个对象
Posted
技术标签:
【中文标题】我想返回节点中匹配对象 id 的上一个对象和下一个对象【英文标题】:I will like to return the previous object and the next object of a matching object id in node 【发布时间】:2021-04-27 02:50:50 【问题描述】:请我是节点 js 和 MongoDB 的新手。 当我想通过 id 检索帖子时,我希望能够检索上一篇文章和下一篇文章。 这是我的帖子,它只通过 id 检索当前帖子。
Post.findById(req.params.postId)
.then((existingpost) =>
console.log(Post.find(req.params.postId))
if (existingpost)
res.send(existingpost);
return res.status(404).send(
message: "Post does not exist with id " + req.params.postId,
);
)
.catch((err) =>
if (err.kind === "ObjectId")
return res.status(404).send(
message: "Post does not exist with id " + req.params.postId,
);
return res.status(500).send(
message:
"Some error occurred while retrieving the post with postId " +
req.params.postId,
);
);
;
我目前收到具有这样 id 的对象,这很好。
"_id": "6009f3e294d8a033402a76e7",
"title": "Covid 19 in Italy",
"author": "John Doe",
"createdAt": "2021-01-21T21:36:34.514Z",
"updatedAt": "2021-01-21T21:36:34.514Z",
"__v": 0
但我很乐意接收当前 id 的对象、前一个对象和下一个对象。 像这样的。
[
"_id": "3230g5e382d8a033402a76e7",
"title": "Effect of Covid on the Economy",
"author": "John Doe",
"createdAt": "2021-01-21T21:36:34.514Z",
"updatedAt": "2021-01-21T21:36:34.514Z",
"__v": 0
,
"_id": "6009f3e294d8a033402a76e7",
"title": "Covid 19 in Italy",
"author": "John Doe",
"createdAt": "2021-01-21T21:36:34.514Z",
"updatedAt": "2021-01-21T21:36:34.514Z",
"__v": 0
,
"_id": "4567hye294d8a033402a76e7",
"title": "Life after Covid",
"author": "John Doe",
"createdAt": "2021-01-21T21:36:34.514Z",
"updatedAt": "2021-01-21T21:36:34.514Z",
"__v": 0
]
【问题讨论】:
【参考方案1】:由于它是一个 UUID,因此这种方法可能会对您有所帮助..
$sort
按 asc 排序文档
$group
和 $unwind
获取索引
$facet
将传入数据分类为current
和allDocs
我们知道 current 只是一个对象,所以我们使用$unwind
来解构数组
我们已经知道索引,所以我们使用$filter
来获取上一个、当前和下一个使用索引
$unwind
解构数组
$replaceRoot
使对象到根
这是脚本
db.collection.aggregate([
$sort: createdAt: 1 ,
$group:
_id: null,
data: $push: "$$ROOT"
,
$unwind: path: "$data", includeArrayIndex: "index" ,
$facet:
current: [
$match: "data._id": "3230g5e382d8a033402a76e7"
],
allDocs: [
$match:
]
,
$unwind: "$current"
,
$project:
docs:
$filter:
input: "$allDocs",
cond:
$or: [
$eq: [ "$$this.index", $subtract: [ "$current.index", 1 ] ] ,
$eq: [ "$$this.index", "$current.index" ] ,
$eq: [ "$$this.index", $add: [ "$current.index", 1 ] ]
]
,
"$unwind": "$docs" ,
"$replaceRoot": "newRoot": "$docs.data"
])
工作Mongo playground
有很多方法可以做到这一点,这是其中一种方法。如果你觉得你有很多文档,那么尽量避免使用昂贵的$unwind
,在这种情况下你可以尝试使用createdDate
而不是索引
【讨论】:
【参考方案2】:我不确定有没有直接的方法可以做到这一点,你可以尝试聚合,
使用 UUID 和 CreatedAt:
$facet
获取all
中的所有文档,然后按createdAt
升序排序
$let
定义变量 states
与开始和总文档,
$cond
检查条件,如果输入 uuid 的索引为零,则返回 start: 0
和 total: 2
我们必须从所有数组中切片的文档,否则获取当前索引并减去负 1 和 total: 3
in
返回基于 start
和 total
的切片文档
Post.aggregate([
$facet: all: [ $sort: createdAt: 1 ] ,
$project:
result:
$let:
vars:
states:
$cond: [
$eq: [ $indexOfArray: ["$all._id", req.params.postId] , 0] ,
start: 0, total: 2 ,
start:
$subtract: [ $indexOfArray: ["$all._id", req.params.postId] , 1]
,
total: 3
]
,
in: $slice: ["$all", "$$states.start", "$$states.total"]
])
Playground
使用 ObjectID:
使用mongoose.Types.ObjectId
将您的字符串输入ID req.params.postId
转换为对象ID
$facet
分离结果,
首先,$match
获取当前和下一个文档,$sort
_id
按降序排列,$limit
2
第二,$match
获取上一个文档,$sort
_id
降序排列,$limit
1
$project
使用 $concatArrays
连接数组 first
和 second
后得到结果
req.params.postId = mongoose.Types.ObjectId(req.params.postId);
Post.aggregate([
$facet:
first: [
$match: _id: $gte: req.params.postId ,
$sort: _id: 1 ,
$limit: 2
],
second: [
$match: _id: $lt: req.params.postId ,
$sort: _id: -1 ,
$limit: 1
]
,
$project: result: $concatArrays: ["$first", "$second"]
])
Playground
【讨论】:
这是 ObjectId 还是 UUID?如果是 UUID,你会怎么比较!!哦哦可能是一个ObjectId,因为他以字符串的形式发帖,所以我提出了这个问题。 OP 在标题中提到了对象 ID,如果他发布字符串,我必须将其与对象一致,但我不知道如何处理 UUID 你有什么线索吗? . 我只是想有索引或(也可能与创建日期一起使用)。工作mongoplayground.net/p/f3Mc6nUk8Qv。可能是一个很长的方法 @turivishal 感谢您的代码。上面的id不是结构化id,是uuid。 @turivishal 我只是发布了我的答案,因为他说它是一个 uuid。无论两个答案都是正确的,取决于 _id 类型以上是关于我想返回节点中匹配对象 id 的上一个对象和下一个对象的主要内容,如果未能解决你的问题,请参考以下文章
SparkSql 查询以从 cassandra 获取定义值的上一行和下一行