MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

mongodb:Abfrage der ersten Zeilen, in denen die Summe einer bestimmten Spalte größer oder gleich C ist

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.