目前僅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();
});
});
});
});
});
我希望這個代碼可以幫助你和其他人誰遇到這個問題。