MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Проверете дали полето съществува в поддокумент на масив

По принцип искате $elemMatch и $exists оператор, тъй като това ще провери всеки елемент, за да види дали условието „полето не съществува“ е вярно за всеки елемент:

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

});

Това връща само втория документ, тъй като полето не присъства в един от поддокументите на масива:

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

Имайте предвид, че това се „различава“ от тази форма:

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

})

Когато това пита дали "всички" елементи на масива не съдържат това поле, което не е вярно, когато документът има поне един елемент, който има полето. Така че $eleMatch прави условието да бъде тествано спрямо "всеки" елемент от масива и по този начин получавате правилния отговор.

Ако искате да актуализирате тези данни, така че всеки намерен елемент от масив, който не съдържа това поле, трябваше да получи това поле със стойност false ( вероятно ), тогава можете дори да напишете изявление като това:

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

Където .aggregate() резултатът не само съвпада с документите, но филтрира съдържанието от масива, където полето не присъства, така че просто да върне „id“ на този конкретен поддокумент.

След това зацикленият .update() операторите съответстват на всеки намерен елемент от масив във всеки документ и добавят липсващото поле със стойност на съответстващата позиция.

По този начин полето ще присъства във всички поддокументи на всеки документ, където е липсвало преди.

Ако искате да направите такова нещо, тогава би било също така разумно да промените схемата си, за да сте сигурни, че полето винаги е там:

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

Така че следващия път, когато добавите нови елементи към масива във вашия код, елементът винаги ще съществува със стойността си по подразбиране, ако не е изрично зададено друго. Вероятно е добра идея да го направите, както и настройката required в други полета, които винаги искате, като например „id“.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Как да актуализирам полетата на документа на MongoDB само ако не съществуват?

  2. Mongodb – Грешка при Mongoimport невалиден знак

  3. Apache Drill - Първото начално време е високо

  4. Конвертирайте съществуващ атрибут на MongoDB низ в BSON::ObjectId

  5. Добавете поле на елемент от масив в агрегирането на MongoDB