mongoose - 使用 mongoose 查找特定文档之前和之后创建的 10 个文档
问题描述
我是一个没有经验的程序员,我对猫鼬还是很陌生。如果我在问一个愚蠢的问题,请饶了我。
假设我有 100 多个文档的集合。我想指定一个文档并找到之前创建的 10 个文档和该文档之后创建的 10 个文档。
我想到的解决方案之一是这样的:
let firstDoc;
let tenBefore;
let tenAfter;
// find the starting document
document.findById(id, function(err, foundDoc){
if(err) {
...
} else {
firstDoc = foundDoc;
// find the 10 documents before
document
.find({created_at: {$lt: foundDoc.created_at}})
.limit(10)
.exec(function(err, beforeDocs) {
if(err) {...} else {
tenBefore = beforeDocs;
// find the 10 documents after
document
.find({created_at: {$gt: foundDoc.created_at}})
.limit(10)
.exec(function(err, afterDocs) {
if(err) {...} else {
tenAfter = afterDocs;
}
});
}
});
}
});
我还没有尝试过它是否有效,但它显然不是最好的解决方案(一个可怕的解决方案)并且可以被认为是回调地狱。
如果有更多经验和知识的人可以帮助我解决这个问题,将不胜感激。
解决方案
在 ES7 中,您可以使用 async/await 清理回调。您还可以同时运行第二个查询Promise.all
async function() {
const foundDoc = await document.findById(id).catch(err => ...);
const [beforeDocs, afterDocs] = await Promise.all([
document
.find({created_at: {$lt: foundDoc.created_at}})
.sort({created_at: -1}) // sort descending to get latest 10
.limit(10),
document
.find({created_at: {$gt: foundDoc.created_at}})
.sort({created_at: 1}) // sort ascending to get earliest 10
.limit(10),
]);
}
AsyncAwait: https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
Promise.all: https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
您也可以使用聚合在一个请求中完成所有三个查询,但它有点复杂。这将返回您通过 _id 查询的文档,其中包含两个额外的数组字段beforeDocs
和afterDocs
.
示例:https ://mongoplayground.net/p/6KeNaCpaifO
db.collection.aggregate([
{$match: {
_id: 5 // use mongoose.Types.ObjectId('YOUROBJECTID')
}},
{$lookup: {
from: "collection",
as: "beforeDocs",
let: {
"parent_created_at": "$created_at"
},
pipeline: [
{$match: {
// Need to use $expr to access parent created at date
$expr: {$lt: ["$created_at", "$$parent_created_at"]}
}},
{$sort: {created_at: -1}},
{$limit: 10}
]
}},
{$lookup: {
from: "collection",
as: "afterDocs",
let: {
"parent_created_at": "$created_at"
},
pipeline: [
{$match: {
$expr: {$gt: ["$created_at", "$$parent_created_at"]}
}},
{$sort: {created_at: 1}},
{$limit: 10}
]
}},
])
推荐阅读
- elasticsearch - 将 Elasticsearch 查询中的多个子句视为不同的
- java - 如何从 Firebase Storage 获取下载网址?
- firebase - 如何将图像从 Firebase 存储显示到小部件中?
- parallax - 如何在不受玩家时刻影响的情况下为视差层添加运动?例如背景中的云
- playframework - 将 Play 项目移植到 Lagom
- kotlin - 将 url 的内容添加到 Ktor 中的 respondText
- java - log4j 1.x 中错误方法的区别
- python - Tkinter,更改按钮及其命令
- c - 卡在一个 for 循环中,用 C 语言将值输入到一个数组中
- java - 使用 Cucumber 为每个正在运行的线程创建一个 TestNG 运行器类