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

Kontroller, om feltet findes i et underdokument til et array

Du vil grundlæggende have $elemMatch og $exists operator, da dette vil inspicere hvert element for at se, om betingelsen "felt eksisterer ikke" er sand for ethvert element:

Model.find({
  "line_items": {
      "$elemMatch": { "review_request_sent": { "$exists": false } }
  }
},function(err,docs) {

});

Det returnerer kun det andet dokument, da feltet ikke er til stede i et af array-underdokumenterne:

{
        "id" : 2,
        "line_items" : [
                {
                        "id" : 1,
                        "review_request_sent" : false
                },
                {
                        "id" : 39
                }
        ]
}

Bemærk, at dette "adskiller sig" fra denne formular:

Model.find({
  "line_items.review_request_sent": { "$exists": false } 
},function(err,docs) {

})

Hvor det spørger, indeholder "alle" array-elementerne ikke dette felt, hvilket ikke er sandt, når et dokument har mindst ét ​​element, der har feltet til stede. Så $eleMatch får tilstanden til at blive testet mod "hvert" array-element, og dermed får du det korrekte svar.

Hvis du ønskede at opdatere disse data, så ethvert array-element, der blev fundet, som ikke indeholdt dette felt, skulle modtage det felt med værdien false (formodentlig), så kunne du endda skrive et udsagn som dette:

    Model.aggregate(
      [
        { "$match": { 
          "line_items": {
            "$elemMatch": { "review_request_sent": { "$exists": false } }
          } 
        }},
        { "$project": {
          "line_items": {
            "$setDifference": [
              {"$map": {
                "input": "$line_items",
                "as": "item",
                "in": {
                  "$cond": [
                    { "$eq": [ 
                      { "$ifNull": [ "$$item.review_request_sent", null ] },
                      null
                    ]},
                    "$$item.id",
                    false
                  ]
                }
              }},
              [false]
            ]
          }
        }}
    ],
    function(err,docs) {
      if (err) throw err;
      async.each(
        docs,
        function(doc,callback) {
          async.each(
            doc.line_items,
            function(item,callback) {
              Model.update(
                { "_id": doc._id, "line_items.id": item },
                { "$set": { "line_items.$.review_request_sent": false } },
                callback
              );
            },
            callback
          );
        },
        function(err) {
          if (err) throw err;
          // done
        }
      );
    }
  );

Hvor .aggregate() Resultat matcher ikke kun dokumenterne, men filtrerer indhold fra arrayet, hvor feltet ikke var til stede, for blot at returnere "id" for det pågældende underdokument.

Derefter den løkkede .update() sætninger matcher hvert fundne array-element i hvert dokument og tilføjer det manglende felt med en værdi ved den matchede position.

På den måde vil du have feltet til stede i alle underdokumenter til hvert dokument, hvor det manglede før.

Hvis du vil gøre sådan noget, så ville det også være klogt at ændre dit skema for at sikre, at feltet også altid er der:

{id: Number,
  line_items: [{ 
    id: String,
    quantity: Number,
    review_request_sent: { type: Boolean, default: false }
  }],
  total_price: String,
  name: String,
  order_number: Number
}

Så næste gang du tilføjer nye elementer til arrayet i din kode, vil elementet altid eksistere med dets standardværdi, hvis ikke andet udtrykkeligt er angivet. Og det er nok en god idé at gøre det, samt at indstille required på andre felter, du altid ønsker, såsom "id".



  1. C# mongodb driver 2.0 - Hvordan upsert i en bulk operation?

  2. Sådan tilslutter du dig to ekstra samlinger med betingelser

  3. mongodb-godkendelse med forbindelsesstreng

  4. Kafka vask stik:Ingen opgaver tildelt, selv efter genstart