更新或附加到 mongo 中的子集合 [英] Update or append to a subcollection in mongo

查看:38
本文介绍了更新或附加到 mongo 中的子集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含子集合的集合.在一个请求中,如果不存在匹配项,我想更新子集合中的记录或附加到它.作为奖励,我还希望此更新是合并而不是覆盖.

I have a collection containing a subcollection. In one request, I would like to update a record in the subcollection or append to it if a match doesn't exist. For a bonus point I would also like this update to be a merge rather than an overwrite.

一个粗略的例子:

// Schema
{
    subColl: [
        {
            name: String,
            value: Number,
            other: Number,
        },
    ];
}

// Existing record
{
    _id : 123,
    subColl: [
        {name: 'John',
        value: 10,
        other: 20}
    ]
}

// example
const update = { _id: 123, name: 'John', other: 1000 };
const { _id, name, other } = update;
const doc = await Schema.findById(_id);
const idx = doc.subColl.findIndex(({ name: nameInDoc }) => nameInDoc === name);
if (idx >= 0) {
    doc.subColl[idx] = { ...doc.subColl[idx], other };
} else {
    doc.subColl.push({ name, other });
}
doc.save();

目前我可以通过拉取记录并手动执行更新/追加来实现此结果,但我假设使用纯 mongo 查询实现它会快得多.

Currently I can achieve this result by pulling the record, and doing the update/append manually but I am assuming that achieving it with a pure mongo query would be much faster.

我试过了:

Schema.findOneAndUpdate(
    { _id: 123, 'subColl.name': 'John' },
    { $set: { 'subColl.$': [{ name: 'John', other: 1000 }] } }
)

但这不会处理追加行为,也不会将对象与现有记录合并,而是完全覆盖它.

but this won't handle the append behaviour and also doesn't merge the object with the existing record, rather it overwrites it completely.

推荐答案

我不确定在单个查询中是否有任何直接的方法可以做到这一点,

I am not sure is there any straight way to do this in single query,

  • $cond 检查名称是否在 subColl 数组中,
  • true 条件,需要与现有对象合并,$map 迭代循环,检查条件是否匹配条件,然后使用 $mergeObjects<将新数据对象与当前对象合并/li>
  • 假条件,需要使用$concatArrays
  • 连接数组、当前subColl数组和新对象
  • $cond to check name is in subColl array,
  • true condition, need to merge with existing object, $map to iterate loop, check condition if matches condition then merge new data object with current object using $mergeObjects
  • false condition, need to concat arrays, current subColl array and new object using $concatArrays
const _id = 123;
const update = { name: 'John', other: 1000 };

Schema.findOneAndUpdate(
  { _id: _id },
  [{
    $set: {
      subColl: {
        $cond: [
          { $in: [update.name, "$subColl.name"] },
          {
            $map: {
              input: "$subColl",
              in: {
                $cond: [
                  { $eq: ["$$this.name", update.name] },
                  { $mergeObjects: ["$$this", update] },
                  "$$this"
                ]
              }
            }
          },
          { $concatArrays: ["$subColl", [update]] }
        ]
      }
    }
  }]
)

游乐场

这篇关于更新或附加到 mongo 中的子集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆