Abfrage
es getan werden könnte Aggregation Rahmen verwenden. Betrachten wir die nächste Aggregations Pipeline
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
C = 1 =>{ "_id": 1, "c": 2 }
C = 8 =>[ { "_id": 2, "c": 6 }, { "_id": 1, "c": 2 } ]
C = 9 =>[ { "_id": 3, "c": 1 }, { "_id": 2, "c": 6 }, { "_id": 1, "c": 2 } ]
=
C 10 =>
Erläuterung
Die grundlegende Idee dahinter ist helper Array für jedes Dokument in der Sammlung (Stufen 1-3)
zu konstruieren
mit $slice
Array aggregati auf Operator und dann mit Summe aller Elemente ersetzen (Stufen 4-5)
{ "_id" : 1, "c" : 2 } -> csum = 2
{ "_id" : 2, "c" : 6 } -> csum = 8
{ "_id" : 3, "c" : 1 } -> csum = 9
Verwendung $unwind
Stufe und $sum
Gruppe Akkumulator Operator enthält.
konstruieren dann einen anderen helper Array von Dokumenten mit csum >= C
(Stufe 6)
/* Ex. (C = 8) */
gteC = [ { "_id" : 3, "c" : 1, "csum" : 9 }, { "_id" : 2, "c" : 6, "csum" : 8 } ]
Der letzte Schritt ist es, alle Dokumente mit csum <= Min { gteC.csum }
abzurufen. Dies erfolgt unter Verwendung von $filter
Array-Aggregationsoperator (Stufe 7).
Ich bin aber nicht sicher, dass dies die effizienteste Aggregation Pipeline (für Verbesserungsvorschläge dankbar sein) zu erreichen, was Sie wollen.
PS Bevor Sie die Abfrage testen, vergessen Sie nicht, den Namen der Sammlung zu ändern und SET_DESIRED_VALUE_FOR_C_HERE zu ersetzen.