sql >> Databasteknik >  >> NoSQL >> MongoDB

mongodb:fråga de första raderna där summan av specifik kolumn är större eller lika med C

Fråga

Det kan göras med aggregationsramverket . Överväg nästa sammanställningspipeline

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) */
]);

Resultat

Förklaring

Grundidén bakom det är att konstruera hjälpararray för varje dokument i samlingen (steg 1-3 )

{ "_id" : 1, "c" : 2 } -> cs = [ 2 ]
{ "_id" : 2, "c" : 6 } -> cs = [ 2, 6 ]
{ "_id" : 3, "c" : 1 } -> cs = [ 2, 6, 1 ]

med $slice arrayaggregationsoperator och ersätt den sedan med summan av alla element som den innehåller (steg 4-5 )

{ "_id" : 1, "c" : 2 } -> csum = 2
{ "_id" : 2, "c" : 6 } -> csum = 8
{ "_id" : 3, "c" : 1 } -> csum = 9

med $unwind steg och $sum gruppackumulatoroperatör .

Konstruera sedan en annan hjälparray av dokument med csum >= C (steg 6 )

/* Ex. (C = 8) */
gteC = [ { "_id" : 3, "c" : 1, "csum" : 9 }, { "_id" : 2, "c" : 6, "csum" : 8 } ]

Det sista steget är att hämta alla dokument med csum <= Min { gteC.csum } . Detta görs med $filter arrayaggregationsoperator (steg 7 ).

Det är jag dock inte säker på att detta är det mest effektiva aggregeringspipeline (kommer att vara tacksam för alla förbättringsförslag) för att uppnå det du vill.

PS Innan du testar frågan, glöm inte att ändra namnet på samlingen och ersätta SET_DESIRED_VALUE_FOR_C_HERE.




  1. Röstsystem med Backbone.js

  2. Autentiseringsfel vid åtkomst till mongodb via Spring Boot-appen

  3. Bulkinsats i MongoDB med mungo

  4. Få de nödvändiga dokumenten från båda samlingarna i en fråga i MongoDB-3.2.7