2016-08-06 7 views

Antwort

0

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 $sliceArray 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 $sumGruppe 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 $filterArray-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.

Verwandte Themen