Interroga
Potrebbe essere fatto utilizzando framework di aggregazione . Considera la prossima sezione di aggregazione
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) */
]);
Risultati
Spiegazione
L'idea di base è quella di costruire array di supporto per ogni documento della raccolta (fasi 1-3 )
{ "_id" : 1, "c" : 2 } -> cs = [ 2 ]
{ "_id" : 2, "c" : 6 } -> cs = [ 2, 6 ]
{ "_id" : 3, "c" : 1 } -> cs = [ 2, 6, 1 ]
utilizzando $slice
operatore di aggregazione di array e quindi sostituirlo con la somma di tutti gli elementi che contiene (fasi 4-5 )
{ "_id" : 1, "c" : 2 } -> csum = 2
{ "_id" : 2, "c" : 6 } -> csum = 8
{ "_id" : 3, "c" : 1 } -> csum = 9
utilizzando $unwind
stage e $sum
operatore accumulatore di gruppo .
Quindi costruisci un altro array di documenti di supporto con csum >= C
(fase 6 )
/* Ex. (C = 8) */
gteC = [ { "_id" : 3, "c" : 1, "csum" : 9 }, { "_id" : 2, "c" : 6, "csum" : 8 } ]
L'ultimo passaggio consiste nel recuperare tutti i documenti con csum <= Min { gteC.csum }
. Questo viene fatto utilizzando $filter
operatore di aggregazione di array (fase 7 ).
Tuttavia, io non certo che questo è il più efficiente pipeline di aggregazione (sarò grato per eventuali suggerimenti di miglioramento) per ottenere ciò che desideri.
PS Prima di testare la query non dimenticare di cambiare il nome della raccolta e di sostituire SET_DESIRED_VALUE_FOR_C_HERE.