![](/img/trans.png)
[英]Geospatial Box query - Mongoose, Node.js MongoDB - returns no results
[英]How to paginate aggregation query results in MongoDB and get a total document count (Node.js + Mongoose)?
我想通过 $limit 和 $skip 对我的查询结果进行分页,并获得通过查询的文档总数。
我现在对结果进行分页是这样的:
const startIndex = (page - 1) * limit
const endIndex = page * limit
const resultObject = {}
resultObject.totalCount = await model.countDocuments(query).exec()
if (endIndex < results.totalCount)
resultObject.next = {page: page + 1, limit}
if (startIndex > 0)
results.prev = {page: page - 1, limit}
resultObject.results = await query.limit(limit).skip(startIndex).exec()
这会产生 2 个问题:
countDocuments
返回 0,即使当我执行query.exec()
时我得到正确的结果(> 0) 所以我的问题是如何在获取文档计数的同时对结果进行分页,就像我现在只使用 1 个查询(并使其与聚合查询一起使用)这样我就可以构建我的resultObject
“我执行查询两次(你甚至可以在 1 中执行此查询吗?)”不,你不能,实现此目的的唯一方法是获取整个集合,然后在代码中返回所需的文档,这显然是一个非常糟糕的解决方案。
现在这有点棘手,从技术上讲, countDocuments是一个只执行管道的包装器:
该方法用 $sum 表达式包装 $group 聚合阶段以执行计数
意义
db.collection.countDocuments({});
等于:
db.collection.aggregate([
{
$group: {
_id: null,
count: {$sum: 1}
}
}
]);
然而,不同的驱动程序以不同的方式支持此命令,例如nodejs
Mongo 驱动程序不允许使用此处指定的某些表达式。 您还使用mongoose
,它可能有其他更改。
如果不查看您的确切查询,就很难说出它失败的原因,但是如果您找不到我推荐的原因,那就是执行包装管道。
我找到了一种方法来获取查询的结果,并在同一次“旅行”中对数据库进行计数(仍然是 2 个查询,但在数据库中,因此速度要快得多)
关键是使用$facet
(mongodb 3.4+):
const pipeline = [
{YOUR_QUERY},
{
$facet: {
paginatedResults: [{$skip: startIndex}, {$limit: limit}],
totalCount: [{$count: 'count'}]
}
},
{
$addFields: {
total: {
$ifNull: [{ $arrayElemAt: ['$totalCount.count', 0]}, 0]
}
}
},
{
$project: {
paginatedResults: 1,
total: 1
}
}
]
解释: $facet
在同一个输入(我们的查询结果)上执行多个管道,我们可以有 1 个管道用于对结果进行分页,1 个用于计算总数。
由于$count
返回一个包含count
字段的 object,并且 facet 包装在一个数组中,因此$addFields
管道将实际count
数值提取为total
字段。 然后我只使用$project
删除不再需要的totalCount
,这就是结果:
{
paginatedResults: [RESULTS],
total: 34
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.