Forespørgsel
Det kunne gøres ved hjælp af aggregationsramme . Overvej den næste aggregeringspipeline
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) */
]);
Resultater
Forklaring
Den grundlæggende idé bag det er at konstruere hjælper array for hvert dokument i samlingen (trin 1-3 )
{ "_id" : 1, "c" : 2 } -> cs = [ 2 ]
{ "_id" : 2, "c" : 6 } -> cs = [ 2, 6 ]
{ "_id" : 3, "c" : 1 } -> cs = [ 2, 6, 1 ]
ved hjælp af $slice
array aggregation operator og erstat den derefter med summen af alle elementer, den indeholder (trin 4-5 )
{ "_id" : 1, "c" : 2 } -> csum = 2
{ "_id" : 2, "c" : 6 } -> csum = 8
{ "_id" : 3, "c" : 1 } -> csum = 9
ved hjælp af $unwind
fase og $sum
gruppeakkumulatoroperatør .
Konstruer derefter en anden hjælpearray af dokumenter med csum >= C
(trin 6 )
/* Ex. (C = 8) */
gteC = [ { "_id" : 3, "c" : 1, "csum" : 9 }, { "_id" : 2, "c" : 6, "csum" : 8 } ]
Det sidste trin er at hente alle dokumenter med csum <= Min { gteC.csum }
. Dette gøres ved hjælp af $filter
array aggregation operator (trin 7 ).
Det er jeg dog ikke sikker på, at dette er det mest effektive aggregeringspipeline (vil være taknemmelig for eventuelle forbedringsforslag) for at opnå det, du ønsker.
PS Inden du tester forespørgslen, glem ikke at ændre navnet på samlingen og erstatte SET_DESIRED_VALUE_FOR_C_HERE.