2013-07-06 54 views
0

我有一個數據結構是這樣的:MongoDB的更新陣列中的任何匹配指數

{ 
students: [ 
       { name: "john", school: 102, age: 4 }, 
       { name: "jess", school: 102, age: 11 }, 
       { name: "jeff", school: 108, age: 7 } 
      ] 
} 
{ 
students: [ 
       { name: "ajax", school: 100, age: 7 }, 
       { name: "achilles", school: 100, age: 8 }, 
      ] 
} 
{ 
students: [ 
       { name: "bob", school: 100, age: 7 }, 
       { name: "manuel", school: 100, age: 8 }, 
      ] 
} 

我想更新的文件,使得誰是7歲學生的任何改變學校101有什麼辦法在1個操作中做到這一點?

回答

0

可以通過指定其位置,例如更新的數組:

db.students.update({"students.age":7},{$set: {"students.$.school":101}},true,true) 
1

目前僅MONGO支持更新在匹配聲明瞭c,一個陣列中的單個子文檔。這對於具有您正在更新的唯一標識符(例如_id)的子文檔非常有效,但在有多個符合條件的子文檔(例如學生年齡)時不起作用。

爲了證明這一點,我添加了一個學生「dupey」第一組的學生,因此新的記錄是這樣的:

students: [ 
      { name: "john", school: 102, age: 4 }, 
      { name: "jess", school: 102, age: 11 }, 
      { name: "jeff", school: 108, age: 7 }, 
      { name: "dupey", school: 102, age: 7 } 
     ] 

這裏是蒙戈更新語句,並在更新完成後的數據結果:

> db.students.update({"students.age":7},{$set: {"students.$.school":101}},true,true); 
> db.students.find({}, { _id: 0 }); 
{ "students" : [ { "name" : "john", "school" : 102,  "age" : 4 }, { "name" : "jess", "school" : 102,  "age" : 11 }, { "name" : "jeff", "school" : 101,  "age" : 7 }, { "name" : "dupey", **"school" : 102**,  "age" : 7 } ] } 
{ "students" : [ { "name" : "ajax", "school" : 101,  "age" : 7 }, { "name" : "achilles", "school" : 100,  "age" : 8 } ] } 
{ "students" : [ { "name" : "bob",  "school" : 101,  "age" : 7 }, { "name" : "manuel", "school" : 100,  "age" : 8 } ] } 

通知dupey的學校還沒有被改變。有一個mongo功能請求來支持這一點。在此之前,這必須分解成多個陳述。這是我在幾個星期前寫過的一些代碼,當我遇到類似的問題時。

var mongoose = require('mongoose'), 
    async = require('async'); 

mongoose.connect('mongodb://127.0.0.1/products'); 

var PartsSchema = new mongoose.Schema({ 
     type: String 
     , partNbr: Number 
    }); 

var ProductSchema = new mongoose.Schema({ 
     sku: { type: String, unique: true } 
     , sku_type: String 
     , parts: [PartsSchema] 
    }); 

Product = mongoose.model('Product', ProductSchema); 

Product.remove(function(err) { 
     if (err) { console.log("unable to remove: " + err); return; } 
    }); 

var cigars = new Product({ 
     sku: 'cigar123', 
     sku_type: 'smoking', 
     parts: [{type: 'tobacco', partNbr: 4}, {type: 'rolling paper', partNbr: 8}, {type: 'tobacco', partNbr: 4}] 
    }); 

var cigarillo = new Product({ 
     sku: 'cigarillo456', 
     sku_type: 'smoking', 
     parts: [{type: 'tobacco', partNbr: 4}, {type: 'crush paper', partNbr: 12}] 
    }); 

function updateProducts(sku_type, part_type, callback) { 

    function updateProduct(product_record, callback) { 

     function denormParts(part_records, sku_id) { 
      var returnArray = []; 
      part_records.forEach(function(item) { 
        var record = { sku_id: sku_id, part_type: item.type, part_id: item._id } 
        returnArray.push(record); 
       }); 
      return returnArray; 
     function updateParts(part_record, callback) { 
      if (part_record.part_type != part_type) { 
       return callback(null); 
      } 
      console.log("updating based on: " + part_record.sku_id + " " + part_record.part_id); 
      Product.update({ _id: part_record.sku_id, 'parts._id': part_record.part_id }, 
          { $set: { 'parts.$.partNbr': 5 } }, 
          function(err, numAffected) { 
           if (err) { console.log("err4: " + err); return callback(err); } 
           console.log("records updated: " + numAffected); 
           callback(null); 
          }); 
     } 

     var denormedParts = denormParts(product_record.parts, product_record._id); 
     console.log("calling updateParts with: " + JSON.stringify(denormedParts)); 
     async.map(denormedParts, updateParts, function(err) { 
         if (err) { console.log("errored out: " + err); callback(err); } 
         callback(null); 
        }); 
    } 

    Product.find({ "parts.type": part_type, "sku_type": sku_type }, 
       function(err, docs) { 
        if (err) { console.log("err3: " + err); return callback(err); } 
        console.log(docs); 
        async.map(docs, updateProduct, function(err) { 
          if (err) { console.log("err4: " + err); return callback(err); } 
          callback(null); 
         }); 
       }); // end Product.find                                         
} 


cigars.save(function(err, product1) { 
     if(err) { console.log("err1: " + err); return err; } 
     console.log("saved: " + product1); 
     cigarillo.save(function(err, product2) { 
       if(err){ console.log("err2: " + err); return err; } 
       console.log("saved: " + product2); 
       updateProducts('smoking', 'tobacco', function(err) { 
         Product.find({}, function(err, docs) { 
           if (err) { console.log("err5: " + err); return err; } 
           console.log("updated data: " + docs); 
           Product.remove(function(err) { 
             if (err) { console.log("err6: " + err); return err; } 
             process.exit(); 
            }); 
          }); 
        }); 
      }); 
    }); 

我希望這個代碼可以幫助你和其他人誰遇到這個問題。