MongoDB更新子文档更改其_id

Haf*_*fez 6 mongoose mongodb node.js

我有下一个文档,我想更新 id 为 21 的地址,将别名更改为“Family”。我跑User.update({ _id: 2, 'addresses._id': 21 }, { 'addresses.$': newAddress });

效果很好,但有一个恼人的副作用,那就是 Mongo 会为子文档生成一个新的 id。有没有办法在不获取新ID的情况下更新子文档?

'user': {
  '_id': 2,
  'addresses': [
    {
      '_id': '20',
      'alias': 'Work',
      'postal_code': 1235
    },
    {
      '_id': '21',
      'alias': 'Home',
      'postal_code': 1235
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

我已经使用解决了这个问题

User.update(
  { _id: req.user._id, 'addresses._id': addressId },
  { $set: {
    'addresses.$.alias': newAddress.alias,
    'addresses.$.address': newAddress.address,
    'addresses.$.areaId': newAddress.areaId,
    'addresses.$.cityId': newAddress.cityId,
    'addresses.$.postal_code': newAddress.postal_code
  } }
);
Run Code Online (Sandbox Code Playgroud)

这不会更改子文档的 id,但出于明显的原因我不喜欢这个解决方案。

Haf*_*fez 5

添加到 JasonCust 的答案中,正确的方法是将旧 id 注入新地址以保持 id 不变并避免输入每个单独的密钥。

下面是一个例子:

  const userSchema = new Schema({
    addresses: [{ country: String }]
  });

  const User = mongoose.model('User', userSchema);
  const user = await User.create({
    addresses: [
      { country: 'Egypt' }
    ]
  });

  const oldAddressId = user.addresses[0]._id;

  //
  const newAddress = {
    _id: oldAddressId,
    country: 'Japan'
  };

  await User.updateOne({ 'addresses._id': oldAddressId }, { 'addresses.$': newAddress });
  const userAfterUpdate = await User.findOne({ _id: user._id });

  assert.equal(userAfterUpdate.addresses[0].country, 'Japan');
  assert.equal(userAfterUpdate.addresses[0]._id.toString(), oldAddressId.toString());
Run Code Online (Sandbox Code Playgroud)