【问题标题】:Delete all documents from a collection based on a condition and create missing ones根据条件从集合中删除所有文档并创建缺失的文档
【发布时间】:2020-08-10 03:25:19
【问题描述】:

现在这是我已经设法实现的东西,我只是想知道是否有更简单/更好的方法来实现它,因为我刚刚开始使用 Mongoose 和 MongoDB。

假设我在一个集合中有几个具有名称字段的文档(我希望我的术语正确),例如:[{Name: "Name1"}, {Name: "Name3"}],我们称之为NamesConfiguration

现在我还有一个配置数组config,名称为:["Name1", "Name2"]

我的目标是从NamesConfiguration 中删除所有在config 数组中不存在的名称,然后从config 数组中添加所有在NamesConfiguration 中不存在的名称,所以我的最终集合应该是[{Name: "Name1"}, {Name: "Name2"}]

try {
  const config = ["Name1", "Name2"];
  const NamesConfiguration = await UIConfiguration.find(); // getting all available nameconfigs from the db

  NamesConfiguration.forEach(async (nameConfig) => {
    if (!config.includes(nameConfig.Name)) {  // loop through and delete the ones that are not within the array
      console.log("deleting" + nameConfig.Name);
      await UIConfiguration.findOneAndDelete({ Name: nameConfig.Name });
    }
  });

  // loop through the array and see if the names are present
  config.forEach(async (configName) => {
    let found = NamesConfiguration.find((nameConfig) => nameConfig.Name === configName);

    // create new nameconfig if not found
    if (!found) {
      console.log("Creating" + configName);
      let NameConfigToAdd = new UIConfiguration({
        Name: configName
      });
      await NameConfigToAdd.save();
    }
  });
} catch (e) {
  console.log(e);
}

我只是想知道是否有更好、“更合适”的方式来执行该操作。在我的情况下,即使这可能会影响性能,它也不会成为一个问题,因为我永远不会有超过 10-20 个条目。

按照优素福的回答解决了这个问题:

  const availableConfigs = (await UIConfiguration.find()).map(
    (availableConfig) => {
      return availableConfig.Name;
    }
  );
  const configNamesToAdd = robotsNames
    .filter((robotName) => !availableConfigs.includes(robotName))
    .map((configName) => {
      return {
        Name: configName
      };
    });

  const deleteCondition = {
    Name: { $not: { $in: robotsNames } },
  };

  await UIConfiguration.deleteMany(deleteCondition);
  await UIConfiguration.insertMany(configNamesToAdd);

【问题讨论】:

    标签: node.js mongodb mongoose


    【解决方案1】:

    您可以按照以下步骤进行操作:

    1. 删除集合中Name 字段值存在于config 数组中的所有文档。

      要删除Name 字段值不在config 数组中的任何文档,请使用$in$not 运算符编写删除查询。

      UIConfiguration.deleteMany({ Name: { $not: { $in: ["Name1", "Name2"] } } });
      
    2. 获取Name 字段值存在于config 数组中的所有文档。您可以使用$in 运算符来做到这一点

      UIConfiguration.find({ Name: { $in: ["Name1", "Name2"] } });
      
    3. 遍历返回的文档数组并过滤掉config数组中与任何文档的Name字段值不匹配的名称字符串。

    4. 最后,使用.insertMany方法将过滤后数组中的所有名字插入集合中

      UIConfiguration.insertMany([/* filtered name objects */]);  
      

    有关上述方法和运算符的更多详细信息,请参阅:

    【讨论】:

    • 谢谢,删除工作,但我无法弄清楚插入。如果我从 db 中的 Name1 和 Name3 开始,并且数组是 1 和 2,则在 db 中删除后应该只有 Name1,因为 3 不在 cfg 数组中,这是可行的。然后 Name2 应该添加到数据库中,因为它存在于 cfg 数组中但在数据库中缺失。在这种情况下,已删除的文档是无关紧要的,因此它会确定数组中哪些项目要添加到数据库中,而这些项目尚不存在
    • 从第 3 步开始阅读。在这一步中,我提到了如何确定在删除操作后应该在集合中添加哪些名称。删除的文档不相关,但删除的计数不相关,需要检查config数组中是否有应该添加到集合中的名称。
    • 这就是我的意思,我不明白删除的计数是如何相关的,如果我的文件是 Name1 Name3 Name4 Name5 Name6 Name7 等等,直到 100 并且我的配置是 Name1 Name2 而已,那么会有98个已删除的文档,但只需要添加一个
    • 啊,是的,我明白你的意思。检查更新的答案。您无需检查已删除的文档计数。删除操作后,只需使用$in操作符获取文档即可。
    • 我用我的实现更新了我的问题并接受了你的回答。此外,我认为我不需要在 .find() 上使用过滤器,在这两种情况下它都会给我所有文档。
    猜你喜欢
    • 2021-08-18
    • 2018-10-19
    • 2020-09-08
    • 1970-01-01
    • 2018-08-13
    • 2023-03-24
    • 2019-03-18
    相关资源
    最近更新 更多