更新猫鼬中的嵌入文档

时间:2021-05-31 18:05:12

标签: javascript mongodb mongoose

我有一个用户和一个高级架构。高级版嵌入在用户中。

const premiumSchema = new mongoose.Schema(
  {
    subscriptionID: {
      type: String,
      required: true,
    },
    guild: {
      type: Object,
      default: {},
    },
    payment_id: {
      type: String,
      required: true,
    },
    expiry: {
      type: Date,
      require: true,
    },
    reminded: {
      type: Boolean,
      default: false,
    },
  },
  { collection: "premium" }
);

const userSchema = new mongoose.Schema({
  discordId: {
    type: String,
    required: true,
  },
  accessToken: {
    type: String,
    required: true,
  },
  premium: {
    type: [premiumSchema],
    required: false,
  },
});

我正在尝试通过以下方式更新我的高级收藏的价值:

const user = await User.findOne({
    "premium._id": new ObjectId(req.body.premiumId),
});
const premium = user.premium.id(new ObjectId(req.body.premiumId));
premium.reminded = true;
await user.save();

问题是它更新了我的 reminded 数组中的 user.premium 属性,但没有在高级集合本身中更新它。我做错了什么吗?

1 个答案:

答案 0 :(得分:0)

您可以使用 findOneAndUpdate 方法和位置运算符直接更新您的用户。

位置运算符 $ 允许您遍历数组并仅更新相应的子文档

const savedUser = await User.findOneAndUpdate(
  {_id: new ObjectId(req.body.premiumId)},
  {$set: {'premium.$.reminded': true}}
);

参见文档:https://docs.mongodb.com/manual/reference/operator/update/positional/

这样您可以更新 User 集合中的子文档,但Premium 集合中的值不会更新。 这是因为当您在 Users 集合中定义 premium 属性时,您是在告诉 mongoose(和 mongodb)将对象保存在用户集合本身中。 在这种情况下,两个集合之间没有引用:数据将仅保存在用户集合中,用作子文档。 您只是为子项定义架构不会在数据库中为子项创建单独的集合,而是将整个子文档嵌入到父项(用户)中。

示例数据:

user1: {
  discordId: { 'abc' },
  accessToken: { 'token' },
  premium: {
    subscriptionID: { 'idSubscription' } 
    guild: { },
    payment_id: { 'idPayment' },
    expiry: { '2021-07-31T20:41:19.618+00:00' },
    reminded: { true }
  },
});

两个 User 和 Premium 集合保持完全独立。 如果您还想升级 Premium 系列,您可以使用两种不同的调用方式来实现,一种用于 User,一种用于 Premium。