MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Sprawdź, czy pole istnieje w poddokumencie tablicy

Zasadniczo chcesz $elemMatch i $exists operatora, ponieważ spowoduje to sprawdzenie każdego elementu, aby sprawdzić, czy warunek „pole nie istnieje” jest spełniony dla dowolnego elementu:

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

});

Zwraca to tylko drugi dokument, ponieważ pole nie występuje w jednym z poddokumentów tablicy:

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

Zauważ, że to "różni się" od tego formularza:

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

})

Tam, gdzie to pytanie, „wszystkie” elementy tablicy nie zawierają tego pola, co nie jest prawdą, gdy dokument ma co najmniej jeden element, który ma to pole. Więc $eleMatch sprawia, że ​​warunek jest testowany z "każdym" elementem tablicy, a tym samym otrzymujesz poprawną odpowiedź.

Jeśli chcesz zaktualizować te dane, aby każdy znaleziony element tablicy, który nie zawierał tego pola, otrzymał to pole z wartością false (przypuszczalnie ), wtedy możesz nawet napisać takie oświadczenie:

    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
        }
      );
    }
  );

Gdzie .aggregate() wynik nie tylko pasuje do dokumentów, ale odfiltrowuje zawartość z tablicy, w której pole nie było obecne, aby po prostu zwrócić "id" tego konkretnego dokumentu podrzędnego.

Następnie zapętlony .update() instrukcje dopasowują każdy znaleziony element tablicy w każdym dokumencie i dodają brakujące pole z wartością w dopasowanej pozycji.

W ten sposób pole będzie obecne we wszystkich poddokumentach każdego dokumentu, w którym wcześniej go brakowało.

Jeśli chcesz zrobić coś takiego, rozsądnie byłoby również zmienić schemat, aby upewnić się, że to pole również zawsze tam jest:

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

Tak więc następnym razem, gdy dodasz nowe elementy do tablicy w kodzie, element zawsze będzie istniał ze swoją wartością domyślną, jeśli nie określono inaczej. I prawdopodobnie jest to dobry pomysł, podobnie jak ustawienie required w innych polach, które zawsze chcesz, np. „id”.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Wstawianie obiektu momentjs do kolekcji Meteor

  2. Rozpoczęcie problemu z używaniem i uruchamianiem usług parzenia [email Protected]

  3. RangeError:Nieprawidłowa długość bufora tablicy - Meteor JS

  4. Chcę pobrać wartości wstawione w określonym dniu za pomocą _id of mongodb

  5. MONGO otrzymuje tylko nazwy dokumentów, ale nie całe dokumenty