当前位置: 首页 > 知识库问答 >
问题:

Mongoose更新多个子文档

潘琪
2023-03-14

我试图更新一个子文档地址(有效),然后更新除上一个子文档之外的多个子文档。基本上,每次地址更改为true时,它都必须将首选的地址更改为true之前的地址更改为false(我正在尝试更新除更改为true的地址之外的所有地址)。

用户文档

js prettyprint-override">_id: ObjectId("5b996f0fd5fbf511709f668f");
addresses: [
  {
    _id: ObjectId("5ba33e0991cd7a3bb85dab7e");
    is_preferred:true
  },
  {
    _id: ObjectId("5ba3e9337310c637207b44cb");
    is_preferred:false
  }
]

下面是我的解决方案:

// model
User = mongoose.model('user', new Schema({
    _id: { type: mongoose.Schema.Types.ObjectId, required: true },
    addresses: [
        {
            _id: { type: mongoose.Schema.Types.ObjectId, required: true },
            is_preferred: { type: Boolean, required: true }
        }
    ],
}, { collection: 'user' }););

// route
router.put('/updateAddress/:addressId', auth, user.updateAddress);

// user.js
exports.updateAddress = wrap(async(req, res, next) => {
    // update one object address `is_preferred` to true and return an array 'addresses' containing it
    const user = await User.findOneAndUpdate(
        { addresses: { $elemMatch: { _id: mongoose.Types.ObjectId(req.params.addressId) } } }, { 'addresses.$': req.body },
        { projection: { 
            addresses: { 
                $elemMatch: { _id: mongoose.Types.ObjectId(req.params.addressId) }
            }
        }, new: true }).lean();
    if (user) {
        // updated object `is_preferred` changed to true, so another objects must be false
        if (user.addresses[0].is_preferred) {
            // doesnt work
            await User.update({ _id: { $ne: mongoose.Types.ObjectId(req.params.addressId) }, is_preferred: true },
                { $set: { addresses: { is_preferred: false } } }, { multi: true });
        }
        res.status(200).json({success: true, message: 'Saved.', new_object: user.addresses[0]});
    } else {
        res.status(400).json({success: false, message: 'Error.'});
    }
});

我可以将用户子文档地址更新为。但是,最好将另一个地址更新为false,否则无法工作。我做错了什么?


共有1个答案

李法
2023-03-14

我建议像您这样的场景使用mongoose中间件prepost模式挂钩。其思想是,您可以通过该中间件在模式中处理它,而不是在控制器中处理它。

唯一的不便是prepost钩子不会在findOneAndUpdate上触发,您需要先执行find,然后执行update

因此,您可以对posthook执行以下操作:

User.post('save', doc => {
  // You can update all the rest of the addresses here.
});

此外,要使更新生效,您需要执行以下操作:

User.update(
   { "addresses._id": { $ne: mongoose.Types.ObjectId(req.params.addressId) }}, 
   { $set: { 'addresses.0.is_preferred': false }}, 
   { multi: true }
)
 类似资料:
  • 我想使用mongoose从多个文档更新多个子文档。 我目前的代码是: 模式的一部分是: 但是这段代码只更新id arr中的最后一个元素。

  • 我有一份这样的文件: 我想通过将其与数量字段(2*800)相乘来更新价格字段,其中的结果将更新/分配给价格。(对于本例,价格更新为1600)。 更新后的文档: 我的选择查询如下: 我怎样才能做到这一点?

  • 问题内容: 使用Mongoose可以一次性在一个(子)文档上设置多个属性吗?我正在尝试做的一个例子: 假设我有以下架构: 然后我想做: 通常,我可以使用运算符来实现此目的,但是我的问题是在此示例中是的子文档(嵌入式架构)。所以当我尝试去做 它替换了由标识的子文档实例。目前,我已经通过手动设置仅字段来“解决”它,但是我希望有一种更好的方法来做到这一点。 问题答案: 基于的字段以编程方式构建对象,以使

  • 我想通过猫鼬进行API调用,以将一批选定的(下面的模式)子文档的日期字段更新为当前日期。 Player模式: 我创建了一个复选框,用户可以在其中选择多个(以及他们的数组中的特定'卡片'子文档),并将所有选定的的特定卡片的日期更改为相同的日期...作为反应,我将相应的ObjectIds在主体中批处理在一起,并将选定的玩家/卡片组合发送到一个对象数组中,如下所示(其中数字表示相同的分组玩家 我正在发送

  • 我有一个mongodb集合的mongoose模式,我将其定义如下: 在数据库集合中,我当前有一个文档,它包含除以外的所有属性的值,用于测试目的。我有一个服务器endpoint,当被调用时,它应该发出一个PUT请求来更新文档并向sketches数组中添加一个对象: 在这个web服务中,我基本上试图通过用户名选择用户文档,用户名作为参数传递给url字符串,如下所示: 由于某种原因,当我尝试使用具有以下

  • 问题内容: 也许是时候了,也许是我淹没在稀疏的文档中,无法将自己的头围在Mongoose中的更新概念上:) 这是交易: 我有一个联系模式和模型(缩短的属性): 我从客户端收到一个包含我需要的字段的请求,并因此使用我的模型: 现在我们解决了这个问题: 如果我打电话,如果使用相同电话号码的联系人已经存在(如预期-唯一),我将收到一条错误消息 我无法致电联系,因为该方法在文档中不存在 如果我对模型调用u