我使用聚合来从mongodb获取记录.
$result = $collection->aggregate(array(
array('$match' => $document),
array('$group' => array('_id' => '$book_id', 'date' => array('$max' => '$book_viewed'), 'views' => array('$sum' => 1))),
array('$sort' => $sort),
array('$skip' => $skip),
array('$limit' => $limit),
));
Run Code Online (Sandbox Code Playgroud)
如果我无限制地执行此查询,则将获取10条记录.但我想保持限制为2.所以我想得到总记录数.如何进行聚合?请指教.谢谢
Anu*_*eek 89
这是在单个查询中同时获得分页结果和结果总数的最常见问题之一.当我终于实现它时,我无法解释我的感受.
$result = $collection->aggregate(array(
array('$match' => $document),
array('$group' => array('_id' => '$book_id', 'date' => array('$max' => '$book_viewed'), 'views' => array('$sum' => 1))),
array('$sort' => $sort),
// get total, AND preserve the results
array('$group' => array('_id' => null, 'total' => array( '$sum' => 1 ), 'results' => array( '$push' => '$$ROOT' ) ),
// apply limit and offset
array('$project' => array( 'total' => 1, 'results' => array( '$slice' => array( '$results', $skip, $length ) ) ) )
))
Run Code Online (Sandbox Code Playgroud)
结果将如下所示:
[
{
"_id": null,
"total": ...,
"results": [
{...},
{...},
{...},
]
}
]
Run Code Online (Sandbox Code Playgroud)
use*_*510 51
从v.3.4(我认为)开始,MongoDB现在有一个名为' facet ' 的新聚合管道运算符,用它们自己的话说:
在同一组输入文档的单个阶段内处理多个聚合管道.每个子管道在输出文档中都有自己的字段,其结果存储为文档数组.
在这种特殊情况下,这意味着人们可以这样做:
$result = $collection->aggregate([
{ ...execute queries, group, sort... },
{ ...execute queries, group, sort... },
{ ...execute queries, group, sort... },
$facet: {
paginatedResults: [{ $skip: skipPage }, { $limit: perPage }],
totalCount: [
{
$count: 'count'
}
]
}
]);
Run Code Online (Sandbox Code Playgroud)
结果将是(总共100个结果):
[
{
"paginatedResults":[{...},{...},{...}, ...],
"totalCount":[{"count":100}]
}
]
Run Code Online (Sandbox Code Playgroud)
Vis*_*iya 49
使用此选项可查找集合中的总计数.
db.collection.aggregate( [
{ $match : { score : { $gt : 70, $lte : 90 } } },
{ $group: { _id: null, count: { $sum: 1 } } }
] );
Run Code Online (Sandbox Code Playgroud)
小智 23
您可以使用toArray函数,然后获取其总记录数的长度.
db.CollectionName.aggregate([....]).toArray().length
Run Code Online (Sandbox Code Playgroud)
pal*_*aѕн 15
以下是在进行 MongoDB 聚合时获取总记录数的一些方法:
$count:db.collection.aggregate([
// Other stages here
{ $count: "Total" }
])
Run Code Online (Sandbox Code Playgroud)
要获得 1000 条记录,这平均需要 2 毫秒,并且是最快的方式。
.toArray():db.collection.aggregate([...]).toArray().length
Run Code Online (Sandbox Code Playgroud)
要获得 1000 条记录,这平均需要 18 毫秒。
.itcount():db.collection.aggregate([...]).itcount()
Run Code Online (Sandbox Code Playgroud)
要获得 1000 条记录,这平均需要 14 毫秒。
小智 14
使用$ count聚合管道阶段来获取文档总数:
查询:
db.collection.aggregate(
[
{
$match: {
...
}
},
{
$group: {
...
}
},
{
$count: "totalCount"
}
]
)
Run Code Online (Sandbox Code Playgroud)
结果:
{
"totalCount" : Number of records (some integer value)
}
Run Code Online (Sandbox Code Playgroud)
小智 10
我是这样做的:
db.collection.aggregate([
{ $match : { score : { $gt : 70, $lte : 90 } } },
{ $group: { _id: null, count: { $sum: 1 } } }
] ).map(function(record, index){
print(index);
});
Run Code Online (Sandbox Code Playgroud)
聚合将返回数组,因此只需循环它并获得最终索引.
其他方式是:
var count = 0 ;
db.collection.aggregate([
{ $match : { score : { $gt : 70, $lte : 90 } } },
{ $group: { _id: null, count: { $sum: 1 } } }
] ).map(function(record, index){
count++
});
print(count);
Run Code Online (Sandbox Code Playgroud)
小智 8
//const total_count = await User.find(query).countDocuments();
//const users = await User.find(query).skip(+offset).limit(+limit).sort({[sort]: order}).select('-password');
const result = await User.aggregate([
{$match : query},
{$sort: {[sort]:order}},
{$project: {password: 0, avatarData: 0, tokens: 0}},
{$facet:{
users: [{ $skip: +offset }, { $limit: +limit}],
totalCount: [
{
$count: 'count'
}
]
}}
]);
console.log(JSON.stringify(result));
console.log(result[0]);
return res.status(200).json({users: result[0].users, total_count: result[0].totalCount[0].count});
Run Code Online (Sandbox Code Playgroud)
@Divergent提供的解决方案确实有效,但根据我的经验,最好有2个查询:
推送$$ ROOT并使用$ slice的解决方案会导致大型集合的文档内存限制为16MB.此外,对于大型集合,两个查询似乎比使用$$ ROOT推送的查询运行得更快.您也可以并行运行它们,因此您只受两个查询中较慢的查询(可能是排序的查询)的限制.
我已经使用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
});
}
});
}
});
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
88795 次 |
| 最近记录: |