2017-01-16 23 views
0

を使用して配列内のドキュメントを更新しました。以下のような文書を作成しました。売り上げフィールドが売り上げフィールド全体よりも小さい場合にのみ更新します。私はドキュメントの配列内のドキュメントを取得する方法を知っており、ドキュメント内の2つのフィールドを比較する方法はわかっていますが、アップデートと一緒に1つの式でそれらをすべて一緒に行うことはできません。

{ 
"_id" : ObjectId("4f7ee46e08403d063ab0b4f9"), 
"name" : "MongoDB", 
"notes" : [ 
      { 
       "_Id" : ObjectId("4f7ee46e08403d063ab0h659") 
       "title" : "Hello MongoDB", 
       "content" : "Hello MongoDB", 
       "total" : 100 
      }, 
      { 
       "_Id" : ObjectId("4f7ee46e08403d083ab0h659") 
       "title" : "ReplicaSet MongoDB", 
       "content" : "ReplicaSet MongoDB", 
       "total" : 200, 
       "sold" : 2  
      }, 
      { 
       "_Id" : ObjectId("4f7ee65e08403d083ab0h659") 
       "title" : "ReplicaSet MongoDB", 
       "content" : "ReplicaSet MongoDB", 
       "total" : 200, 
      } 
     ] 
} 

文書の配列からドキュメントを読むために私の式:

db.Collection.find({'notes._id':ObjectId('58791af46c698c00475e7f41')},{'notes.$':true}) 

私は2つのフィールド

db.Collection.find({ $where : "this.total > this.sold" }); 
+0

何 'sold'が存在していない事例については? – chridam

答えて

0

これに対する最善のアプローチを比較するには、このような式を書くことができるだろう最初に、集計を、文書のリストと、所与の条件に合致する配列要素のサブセット、すなわち、売り上げが全フィールドより少ない部分を決定するための手段として使用することである。 このリストを取得すると、Bulk更新を処理することができます。これにより、少なくとも1つの要求で単一の応答で多くの操作を送信できるようになります。

次の例では、このことについて行くことができる方法を示しています。

var ops = [], 
    cursor = db.collection.aggregate([ 
     { 
      "$redact": { 
       "$cond": [ 
        { 
         "$allElementsTrue": { 
          "$map": { 
           "input": "$notes", 
           "as": "el", 
           "in": { "$gt": [ "$$el.total", "$$el.sold" ] } 
          } 
         } 
        }, 
        "$$KEEP", 
        "$$PRUNE" 
       ] 
      } 
     }, 
     { 
      "$project": { 
       "notes": { 
        "$filter": { 
         "input": "$notes", 
         "as": "el", 
         "cond": { 
          "$and": [ 
           { "$gt": [ "$$el.total", "$$el.sold" ] }, 
           { "$gt": [ "$$el.sold", null ] } 
          ] 
         } 
        } 
       } 
      } 
     } 
    ]); 

cursor.forEach(function(doc) { 
    doc.notes.forEach(function(note){ 
     ops.push({ 
      "updateOne": { 
       "filter": { "_id": doc._id, "notes._id": note._id }, 
       "update": { 
        "$set": { "notes.$.sold": 400 } // update the sold field accordingly 
       } 
      } 
     }); 

     if (ops.length === 500) { 
      db.collection.bulkWrite(ops); 
      ops = []; 
     } 
    }); 
}) 

if (ops.length > 0) 
    db.collection.bulkWrite(ops); 
+0

詳細なクエリをお寄せいただきありがとうございます。配列からドキュメントを返すことはありません。配列の長さは常にzero.lになります。また、(クエリに渡すIDの)ノートの配列から。 –