Mongo更新无法按预期工作

时间:2016-06-01 15:23:12

标签: javascript node.js mongodb mongoose

假设我有这个模型:

var stuffSchema = new mongoose.Schema({
  "id": 1,
  "cars": {
    "suv": [],
    "sports": [],
    "supercar": [{
      "owner": "nick",
      "previousOwners": [
        ObjectId("574e1bc0abfb4a180404b17f"),
        ObjectId("574e1bdeabfb4a180404b180"),
        ObjectId("574e1c4babfb4a180404b181"),
        ObjectId("574e1c67abfb4a180404b182"),
        ObjectId("574e23abd25baf340e678b2d"),
        ObjectId("574e241ec8caa3a81cc85ed5")
      ]
    }]
  }
});

var Stuff = mongoose.model('Stuff', stuffSchema);

如果特定的previousOwners已经存在,我想添加owner,如果具体的话,我想添加一个新的owner 相应的previousOwner owner尚不存在。

这是我试过的:

Stuff.update({
  id: 1,
  'cars.supercar.owner': 'olix'
}, {
  $addToSet: {
    'cars.supercar.$.previousOwners': ObjectId("574e241ec8caa3a81c893e73")
  }
}, {
  $upsert: true
}, function(err) {
  if (err) {
    console.log('Error: ' + err);
  }
});

我希望这会添加一个名为'olix'的新owner,并附带其previousOwners数组。这会使我的文档看起来像这样:

{
  "id": 1,
  "cars": {
    "suv": [],
    "sports": [],
    "supercar": [{
      "owner": "nick",
      "previousOwners": [
        ObjectId("574e1bc0abfb4a180404b17f"),
        ObjectId("574e1bdeabfb4a180404b180"),
        ObjectId("574e1c4babfb4a180404b181"),
        ObjectId("574e1c67abfb4a180404b182"),
        ObjectId("574e23abd25baf340e678b2d"),
        ObjectId("574e241ec8caa3a81cc85ed5")
      ],
      "owner": "olix",
      "previousOwners": [
        ObjectId("574e241ec8caa3a81c893e73")
      ]
    }]
  }
}

根本不起作用。它甚至没有产生错误。 我试过了:

db.stuffs.find({id: 1, 'cars.supercar.owner': 'nick'})

并成功返回文档。只是为了确保我的查询是正确的。

我做错了什么?

2 个答案:

答案 0 :(得分:1)

首先,您的架构定义不正确,请改用:

var stuffSchema = new mongoose.Schema({
    'id': Number,
    'cars': {
        'suv': [],
        'sports': [],
        'supercar': [{
            _id: false,
            'owner': { type: String },
            'previousOwners': [{ type: mongoose.Schema.ObjectId }]
        }]
    }
});

var Stuff = mongoose.model('Stuff', stuffSchema);

将更新查询更改为:

Stuff.update({ 
    id: 1
}, {
    $addToSet: {
        'cars.supercar': {
            'owner': 'olix',
            'previousOwners': [ObjectId('574e241ec8caa3a81c893e75')]
        }
    }
}, function(err) {
    if (err) {
        console.log('Error: ' + err);
    }
});

注意:mongoose检查对象的每个属性,因此如果它的所有者字段和previousOwners数组完全相同,则supercar数组对象是相同的,否则它会将新对象推送到超级数组中。

答案 1 :(得分:0)

我通过手动更新解决了它:

Stuff.findOne({
  id: 1
}, function(err, stuff) {
  if (err) {
    return done(err);
  }

  var ownersList = stuff.cars.supercar.map(function(supercarCar) {
    return supercarCar.owner;
  });

  var ownerIndex = ownersList.indexOf('nick');

  if (ownerIndex != -1) {
    stuff.cars.supercar[ownerIndex].previousOwners.push(ObjectId("574e241ec8caa3a81c893e73"));
  } else {
    stuff.cars.supercar.push({
      owner: 'nick',
      previousOwners: [ObjectId("574e241ec8caa3a81c893e73")]
    })
  }

  stuff.save(function(err) {
    if (err) {
      return done(err);
    }
  });
});

备注
这是一个假文件,所有属性名称都因匿名而被更改。
此处使用了完成功能,因为此代码是在 .pre(' save' >模式实例中运行的。
有些值仅为了示例目的而被硬编码。