Saya telah menggunakan agregasi untuk mengambil catatan dari 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),
));
Jika saya menjalankan kueri ini tanpa batas, maka 10 catatan akan diambil. Tapi saya ingin membatasi 2. Jadi saya ingin menghitung total catatan. Bagaimana saya bisa melakukan dengan agregasi? Mohon saran saya. Terima kasih
Jawaban:
Ini adalah salah satu pertanyaan yang paling umum ditanyakan untuk mendapatkan hasil paginasi dan jumlah total hasil secara bersamaan dalam satu kueri. Saya tidak bisa menjelaskan bagaimana perasaan saya ketika akhirnya saya mencapainya LOL.
$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 ) ) ) ) ))
Hasilnya akan terlihat seperti ini:
[ { "_id": null, "total": ..., "results": [ {...}, {...}, {...}, ] } ]
sumber
{ $group: { _id: null, count: { $sum:1 }, result: { $push: '$$ROOT' }}}
(masukkan setelah{$group:{}}
untuk menghitung jumlah total.Sejak v.3.4 (menurut saya) MongoDB sekarang memiliki operator pipeline agregasi baru bernama ' facet ' yang dengan kata-katanya sendiri:
Dalam kasus khusus ini, ini berarti seseorang dapat melakukan sesuatu seperti ini:
$result = $collection->aggregate([ { ...execute queries, group, sort... }, { ...execute queries, group, sort... }, { ...execute queries, group, sort... }, $facet: { paginatedResults: [{ $skip: skipPage }, { $limit: perPage }], totalCount: [ { $count: 'count' } ] } ]);
Hasilnya adalah (dengan untuk contoh hasil total 100):
[ { "paginatedResults":[{...},{...},{...}, ...], "totalCount":[{"count":100}] } ]
sumber
$project
?Gunakan ini untuk menemukan jumlah total dalam koleksi yang dihasilkan.
db.collection.aggregate( [ { $match : { score : { $gt : 70, $lte : 90 } } }, { $group: { _id: null, count: { $sum: 1 } } } ] );
sumber
Anda bisa menggunakan fungsi toArray dan kemudian mendapatkan panjangnya untuk jumlah catatan total.
sumber
TypeError: Parent.aggregate(...).toArray is not a function
ini adalah kesalahan yang saya berikan dengan solusi ini.Gunakan tahap pipeline agregasi $ count untuk mendapatkan jumlah dokumen total:
Pertanyaan:
db.collection.aggregate( [ { $match: { ... } }, { $group: { ... } }, { $count: "totalCount" } ] )
Hasil:
{ "totalCount" : Number of records (some integer value) }
sumber
Saya melakukannya dengan cara ini:
db.collection.aggregate([ { $match : { score : { $gt : 70, $lte : 90 } } }, { $group: { _id: null, count: { $sum: 1 } } } ] ).map(function(record, index){ print(index); });
Agregat akan mengembalikan array jadi putar saja dan dapatkan indeks akhir.
Dan cara lain untuk melakukannya adalah:
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);
sumber
var
deklarasi ataumap
panggilan. 3 baris pertama dari contoh pertama Anda sudah cukup.Solusi yang diberikan oleh @Divergent memang berfungsi, tetapi menurut pengalaman saya, lebih baik memiliki 2 pertanyaan:
Solusi dengan mendorong $$ ROOT dan menggunakan $ slice mengalami batasan memori dokumen sebesar 16MB untuk koleksi besar. Selain itu, untuk koleksi besar, dua kueri bersama-sama tampaknya berjalan lebih cepat daripada kueri dengan dorongan $$ ROOT. Anda juga dapat menjalankannya secara paralel, jadi Anda hanya dibatasi oleh yang lebih lambat dari dua kueri (mungkin yang menyortir).
Saya telah menyelesaikan solusi ini menggunakan 2 kueri dan kerangka agregasi (catatan - saya menggunakan node.js dalam contoh ini, tetapi idenya sama):
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 }); } }); } }); });
sumber
//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});
sumber
Ini bisa berfungsi untuk beberapa kondisi pertandingan
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) => {})
sumber
Saya membutuhkan jumlah total absolut setelah menerapkan agregasi. Ini berhasil untuk saya:
db.mycollection.aggregate([ { $group: { _id: { field1: "$field1", field2: "$field2" }, } }, { $group: { _id: null, count: { $sum: 1 } } } ])
Hasil:
{ "_id" : null, "count" : 57.0 }
sumber
Berikut beberapa cara untuk mendapatkan jumlah catatan saat melakukan Agregasi MongoDB:
Menggunakan
$count
:db.collection.aggregate([ // Other stages here { $count: "Total" } ])
Untuk mendapatkan 1000 catatan, ini membutuhkan waktu rata-rata 2 md dan merupakan cara tercepat.
Menggunakan
.toArray()
:Untuk mendapatkan 1000 record, dibutuhkan waktu rata-rata 18 ms.
Menggunakan
.itcount()
:Untuk mendapatkan 1000 record, dibutuhkan waktu rata-rata 14 ms.
sumber
Maaf, tapi saya rasa Anda perlu dua pertanyaan. Satu untuk tampilan total dan satu lagi untuk rekaman yang dikelompokkan.
Anda dapat menemukan jawaban yang berguna ini
sumber
Jika Anda tidak ingin mengelompokkan, gunakan metode berikut:
db.collection.aggregate( [ { $match : { score : { $gt : 70, $lte : 90 } } }, { $count: 'count' } ] );
sumber