gpt4 book ai didi

MongoDB - 聚合框架(总数)

转载 作者:IT老高 更新时间:2023-10-28 13:12:17 27 4
gpt4 key购买 nike

在 MongoDB 上运行正常的“查找”查询时,我可以通过在返回的游标上运行“计数”来获得总结果计数(不考虑限制)。因此,即使我将结果集限制为 10(例如),我仍然可以知道结果总数为 53(再次,例如)。

如果我理解正确,那么聚合框架不会返回游标,而只是返回结果。因此,如果我使用 $limit 管道运算符,我如何知道结果的总数,而不管所述限制如何?

我想我可以运行两次聚合(一次通过 $group 计算结果,一次使用 $limit 计算实际有限的结果),但这似乎效率低下。

另一种方法是在 $limit 操作之前将结果总数附加到文档(通过 $group),但这似乎也低效,因为此编号将附加到每个文档(而不是只为集合返回一次)。

我在这里遗漏了什么吗?有任何想法吗?谢谢!

例如,如果这是查询:

db.article.aggregate(
{ $group : {
_id : "$author",
posts : { $sum : 1 }
}},
{ $sort : { posts: -1 } },
{ $limit : 5 }
);

我怎么知道有多少结果可用(在 $limit 之前)?结果不是游标,所以我不能只对它进行计数。

最佳答案

有一个使用 push 和 slice 的解决方案:https://stackoverflow.com/a/39784851/4752635 (@emaniacs 在这里也提到了)。

但我更喜欢使用 2 个查询。推送 $$ROOT 并使用 $slice 的解决方案遇到了 16MB 的大型集合的文档内存限制。此外,对于大型集合,两个查询一起运行似乎比使用 $$ROOT 推送的查询运行得更快。您也可以并行运行它们,因此您只会受到两个查询中较慢的查询(可能是排序的那个)的限制。

  1. 先进行过滤,然后按 ID 分组,得到过滤后的元素个数。不要在这里过滤,没有必要。
  2. 第二个查询过滤、排序和分页。

我已经使用 2 个查询和聚合框架解决了这个解决方案(注意 - 我在这个例子中使用了 node.js):

var aggregation = [
{
// If you can match fields at the begining, match as many as early as possible.
$match: {...}
},
{
// Projection.
$project: {...}
},
{
// Some things you can match only after projection or grouping, so do it now.
$match: {...}
}
];


// Copy filtering elements from the pipeline - this is the same for both counting number of fileter elements and for pagination queries.
var aggregationPaginated = aggregation.slice(0);

// Count filtered elements.
aggregation.push(
{
$group: {
_id: null,
count: { $sum: 1 }
}
}
);

// Sort in pagination query.
aggregationPaginated.push(
{
$sort: sorting
}
);

// Paginate.
aggregationPaginated.push(
{
$limit: skip + length
},
{
$skip: skip
}
);

// I use mongoose.

// Get total count.
model.count(function(errCount, totalCount) {
// Count filtered.
model.aggregate(aggregation)
.allowDiskUse(true)
.exec(
function(errFind, documents) {
if (errFind) {
// Errors.
res.status(503);
return res.json({
'success': false,
'response': 'err_counting'
});
}
else {
// Number of filtered elements.
var numFiltered = documents[0].count;

// Filter, sort and pagiante.
model.request.aggregate(aggregationPaginated)
.allowDiskUse(true)
.exec(
function(errFindP, documentsP) {
if (errFindP) {
// Errors.
res.status(503);
return res.json({
'success': false,
'response': 'err_pagination'
});
}
else {
return res.json({
'success': true,
'recordsTotal': totalCount,
'recordsFiltered': numFiltered,
'response': documentsP
});
}
});
}
});
});

关于MongoDB - 聚合框架(总数),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17767580/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com