sql >> Database teknologi >  >> NoSQL >> MongoDB

mongodb:forespørg på de første par rækker, hvor summen af ​​den specifikke kolonne er større eller lig med C

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.




  1. kan ikke hente data fra databasen efter flere skemaer erklæret (mongoose + express + mongodb

  2. Effektiv måde at søge på med MongoDB og ASP.NET MVC

  3. Er der nogen grunde til, at jeg bør/ikke bør bruge ObjectId'er i mine RESTful url'er

  4. Operatør $arrayElemAt i aggregering med Mongo <3.2