php mongodb获取总数,MongoDB聚合:如何获取总记录数?

我已经使用聚合从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),

));

如果我无限制地执行此查询,则将提取10条记录。 但我想将限制保持为2。因此,我想获取总记录数。 如何进行汇总? 请给我建议。 谢谢

如果只有2,结果将是什么样?

这是在单个查询中同时获得分页结果和结果总数的最常见问题之一。我无法解释当我最终实现它时的感受。

$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 ) ) ) )

))

结果将如下所示:

[

{

"_id": null,

"total": ...,

"results": [

{...},

{...},

{...},

]

}

]

有关此文档:docs.mongodb.com/v3.2/reference/operator/aggregation/group/ ...请注意,使用这种方法,整个非分页结果集必须适合16MB。

这是纯金!我一直在努力使这项工作顺利进行。

谢了,兄弟们 !我只需要{ $group: { _id: null, count: { $sum:1 }, result: { $push: $$ROOT }}}(在{$group:{}}之后插入即可进行总计数查找。

您如何将限制应用于结果集?结果现在是一个嵌套数组

@valen您可以看到代码的最后一行" results => array($ slice => array($ results,$ skip,$ length))"在这里您可以应用限制并跳过参数

很好的答案!

我的生活已经完成,我可以幸福地死

非常有帮助,谢谢! ??

从v.3.4(我认为)开始,MongoDB现在有了一个名为" facet"的新聚合管道运算符,用自己的话说:

Processes multiple aggregation pipelines within a single stage on the same set of input documents. Each sub-pipeline has its own field in the output document where its results are stored as an array of documents.

在这种特殊情况下,这意味着可以执行以下操作:

$result = $collection->aggregate([

{ ...execute queries, group, sort... },

{ ...execute queries, group, sort... },

{ ...execute queries, group, sort... },

$facet: {

paginatedResults: [{ $skip: skipPage }, { $limit: perPage }],

totalCount: [

{

$count: 'count'

}

]

}

]);

结果将是(总共有100个结果):

[

{

"paginatedResults":[{...},{...},{...}, ...],

"totalCount":[{"count":100}]

}

]

从3.4开始,这很好用,应该是公认的答案

要将如此多的结果转换为简单的两个字段对象,我需要另一个$project吗?

现在,这必须是公认的答案。像魅力一样运作。

这应该是今天公认的答案。但是,在与$ facet一起使用分页时,我发现了性能问题。另一个获得投票赞成的答案也有$ slice的性能问题。我发现最好在管道中跳过$ limit和$ limit并单独进行计数。我针对相当大的数据集进行了测试。

使用它来查找集合中的总数。

db.collection.aggregate( [

{ $match : { score : { $gt : 70, $lte : 90 } } },

{ $group: { _id: null, count: { $sum: 1 } } }

] );

谢谢。但是,我在编码中使用了"视图"来获取相应组计数的计数(即,组1 => 2个记录,组3 => 5个记录,依此类推)。我想获取记录数(即总计:120条记录)。希望你理解..

您可以使用toArray函数,然后获取其长度以记录总数。

db.CollectionName.aggregate([....]).toArray().length

不建议用于性能...如果您的数据库很大。

尽管这可能无法作为"合适的"解决方案,但它可以帮助我调试某些内容-即使它不是100%的解决方案,它也可以工作。

这不适用于海量数据

这不是真正的解决方案。

TypeError: Parent.aggregate(...).toArray is not a function这是我使用此解决方案给出的错误。

使用$ count聚合管道阶段来获取文档总数:

查询:

db.collection.aggregate(

[

{

$match: {

...

}

},

{

$group: {

...

}

},

{

$count:"totalCount"

}

]

)

结果:

{

"totalCount" : Number of records (some integer value)

}

这就像魅力一样,但是性能方面好吗?

我这样做是这样的:

db.collection.aggregate([

{ $match : { score : { $gt : 70, $lte : 90 } } },

{ $group: { _id: null, count: { $sum: 1 } } }

] ).map(function(record, index){

print(index);

});

聚合将返回数组,因此只需对其进行循环并获得最终索引。

其他实现方式是:

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);

首先,您不需要var声明或map调用。您的第一个示例的前3行就足够了。

@Divergent提供的解决方案确实有效,但是以我的经验,最好有两个查询:

首先进行过滤,然后按ID分组以获取过滤元素的数量。不要在这里过滤,这是不必要的。

第二个查询,用于过滤,排序和分页。

推送$$ 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

});

}

});

}

});

});

这可能适用于多个匹配条件

const query = [

{

$facet: {

cancelled: [

{ $match: { orderStatus: 'Cancelled' } },

{ $count: 'cancelled' }

],

pending: [

{ $match: { orderStatus: 'Pending' } },

{ $count: 'pending' }

],

total: [

{ $match: { isActive: true } },

{ $count: 'total' }

]

}

},

{

$project: {

cancelled: { $arrayElemAt: ['$cancelled.cancelled', 0] },

pending: { $arrayElemAt: ['$pending.pending', 0] },

total: { $arrayElemAt: ['$total.total', 0] }

}

}

]

Order.aggregate(query, (error, findRes) => {})

//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});

通常最好的做法是将解释性文字与代码答案一起包括在内。

抱歉,但是我认为您需要两个查询。一个用于总视图,另一个用于分组记录。

您可以找到有用的答案

谢谢..我这样认为..但是,聚合没有选择.. :(

我遇到了类似的情况。没有答案,只能进行2个查询。 :( stackoverflow.com/questions/20113731/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值