Abfrage
Dies könnte mit dem Aggregation Framework erfolgen . Betrachten Sie die nächste Aggregationspipeline
db.collectionName.aggregate([
{
$group:
{
"_id": null,
"ds": { $push: "$$ROOT" },
"cs": { $push: "$c" }
}
}, /* (1) */
{ $unwind: "$ds" }, /* (2) */
{
$project:
{
"_id": "$ds._id",
"c": "$ds.c",
"cs": { $slice: [ "$cs", "$ds._id" ] }
}
}, /* (3): */
{ $unwind: "$cs" }, /* (4) */
{
$group:
{
"_id": "$_id",
"c": { $first: "$c" },
"csum": { $sum: "$cs" }
}
}, /* (5) */
{
$group:
{
"_id": null,
"ds": { $push: "$$ROOT" },
"gteC":
{
$push:
{
$cond:
{
if: { "$gte": [ "$csum", SET_DESIRED_VALUE_FOR_C_HERE ] },
then: "$$ROOT",
else: { }
}
}
}
}
}, /* (6) */
{
$project:
{
"_id": 0,
"docs":
{
$filter:
{
input: "$ds",
"as": "doc",
cond: { $lte: [ "$$doc.csum", { $min: "$gteC.csum" } ] }
}
}
}
}, /* (7) */
{ $unwind: "$docs" }, /* (8) */
{ $project: { "_id": "$docs._id", "c": "$docs.c" } } /* (9) */
]);
Ergebnisse
Erklärung
Die Grundidee dahinter ist, ein Hilfsarray zu konstruieren für jedes Dokument in der Sammlung (Phasen 1-3 )
{ "_id" : 1, "c" : 2 } -> cs = [ 2 ]
{ "_id" : 2, "c" : 6 } -> cs = [ 2, 6 ]
{ "_id" : 3, "c" : 1 } -> cs = [ 2, 6, 1 ]
mit $slice
Array-Aggregationsoperator und dann durch die Summe aller darin enthaltenen Elemente ersetzen (Stufen 4-5 )
{ "_id" : 1, "c" : 2 } -> csum = 2
{ "_id" : 2, "c" : 6 } -> csum = 8
{ "_id" : 3, "c" : 1 } -> csum = 9
mit $unwind
stage und $sum
Gruppen-Akkumulator-Operator .
Erstellen Sie dann mit csum >= C
ein weiteres Hilfsarray von Dokumenten (Stufe 6 )
/* Ex. (C = 8) */
gteC = [ { "_id" : 3, "c" : 1, "csum" : 9 }, { "_id" : 2, "c" : 6, "csum" : 8 } ]
Der letzte Schritt besteht darin, alle Dokumente mit csum <= Min { gteC.csum }
abzurufen . Dies erfolgt mit $filter
Array-Aggregationsoperator (Stadium 7 ).
Ich bin es jedoch nicht Das ist sicher das Effizienteste Aggregationspipeline (wird für Verbesserungsvorschläge dankbar sein), um das zu erreichen, was Sie wollen.
PS Vergessen Sie vor dem Testen der Abfrage nicht, den Namen der Sammlung zu ändern und SET_DESIRED_VALUE_FOR_C_HERE zu ersetzen.