पुश और स्लाइस का उपयोग करके एक समाधान है:https://stackoverflow.com/a/39784851/4752635ए> (@emaniacs यहां भी इसका उल्लेख करता है)।
लेकिन मैं 2 प्रश्नों का उपयोग करना पसंद करता हूं। $$ ROOT को आगे बढ़ाने और $slice का उपयोग करने के साथ समाधान बड़े संग्रह के लिए 16MB की दस्तावेज़ मेमोरी सीमा में चलता है। साथ ही, बड़े संग्रह के लिए दो क्वेरी एक साथ $$ ROOT पुश करने वाले की तुलना में तेज़ी से चलती प्रतीत होती हैं। आप उन्हें समानांतर में भी चला सकते हैं, इसलिए आप केवल दो प्रश्नों की धीमी गति से सीमित हैं (शायद एक जो सॉर्ट करता है)।
- पहले फ़िल्टर करने के लिए और फिर फ़िल्टर किए गए तत्वों की संख्या प्राप्त करने के लिए आईडी द्वारा समूहित करें। यहां फ़िल्टर न करें, यह अनावश्यक है।
- दूसरी क्वेरी जो फ़िल्टर, सॉर्ट और पेजिनेट करती है।
मैंने 2 प्रश्नों और एकत्रीकरण ढांचे का उपयोग करके इस समाधान के साथ समझौता किया है (नोट - मैं इस उदाहरण में नोड.जेएस का उपयोग करता हूं):
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
});
}
});
}
});
});