猫鼬查询插入文档不存在?

时间:2021-06-20 12:08:06

标签: mongodb mongoose aggregation-framework

我的 MongoDB 集合如下所示:

[
    { x: "a", t: 1, s: 'old' },
    { x: "a", t: 3, s: 'old' },
    { x: "b", t: 1, s: 'old' },
    { x: "b", t: 4, s: 'old' }
]

我还有一个数组如下:

const list = [
    { x: "a", t: 1, s: 'new' },
    { x: "a", t: 2, s: 'new' },
    { x: "b", t: 2, s: 'new' },
    { x: "b", t: 3, s: 'new' },
]

现在我要插入

<块引用>

列表

以某种方式将数组放入 mongo 集合中:

  • 如果要插入的项目存在于集合中,则不要插入它。
  • 如果要插入的项目存在于集合中,则插入它。

最终结果应该如下:

[
    { x: "a", t: 1, s: 'old' },
    { x: "a", t: 2, s: 'new' },
    { x: "a", t: 3, s: 'old' },
    { x: "b", t: 1, s: 'old' },
    { x: "b", t: 2, s: 'new' },
    { x: "b", t: 3, s: 'new' },
    { x: "b", t: 4, s: 'old' }
]

2 个答案:

答案 0 :(得分:1)

您可以使用带有 upsert 选项的更新查询,

const list = [
  { x: "a", t: 1, s: 'new' },
  { x: "a", t: 2, s: 'new' },
  { x: "b", t: 2, s: 'new' },
  { x: "b", t: 3, s: 'new' }
]

第一个选项,执行每个查询循环,

  • 为更新查询创建一个函数
    • 查询以匹配 xt 字段
    • $setOnInsert 仅当这是一个新文档时才设置字段
    • upsert: true 更新文档(如果已经存在)
  • 循环 list 文档数组并调用更新查询函数
async function updateQuery(doc){
  await YourModel.updateOne(
    { x: doc.x, t: doc.t },
    { $setOnInsert: doc },
    { upsert: true }
  );
}

list.forEach(function(doc) {
  updateQuery(doc);
});

Playground


第二个选项,使用bulkWrite()方法在一个事务中执行所有更新查询,

  • updateQuery 函数创建一个 updateOne 查询
  • 循环 list 文档数组并调用 updateQuery 函数并构造更新查询数组
  • 调用bulkWrite查询函数
function updateQuery(doc){
  return {
    updateOne: {
      filter: { x: doc.x, t: doc.t },
      update: { $setOnInsert: doc },
      upsert: true
    }
  };
}

let bulkWriteQuery = [];
list.forEach(function(doc) {
  bulkWriteQuery.push(updateQuery(doc));
});

await YourModel.bulkWrite(bulkWriteQuery);

答案 1 :(得分:0)

  • 您可以使用 map 函数遍历列表。
  • 然后您可以使用 mongoose findOne 检查该项目是否已存在于集合中。
  • 如果该项目不存在save,则将其添加到集合中并继续迭代。 (该列表应该是您正在使用的猫鼬模式的对象数组)
list.map((item) => {
    if(!Collection.findOne({x: item.x, t: item.t})) {
        try {
            await item.save();
        } catch(error) {
            //handle the error
        }
    }
});