javascript - mongoose 检查 id 是否存在,但该 id 嵌套在数组中

标签 javascript node.js mongodb express mongoose

当我获取新警报时,我想检查新警报的 ID 是否已被记录。问题是该 ID 嵌套在数组内。有alertsDetails 数组,其中包含对象,这些对象有一个_ID 字段,这就是我想要检查的内容。我不知道如何实现这一目标。我得到了下面的代码,但随后我必须迭代结果以检查存在值。我确信一定有更好的方法。

const mongoose = require('mongoose');

const { Schema } = mongoose;

const G2AlertsSchema = new Schema(
  {
    status: { type: String, required: true },
    openDate: { type: Date, required: true },
    alertType: { type: Array, required: true },
    severity: { type: Array, required: true },
    locationName: { type: Array, required: true },
    history: { type: Array, required: true },
    alertDetails: { type: Array, required: false },
    assignedTo: { type: Schema.Types.ObjectId, ref: 'user' },
  },
  {
    timestamps: true,
  },
);

const G2Alerts = mongoose.model('G2Alert', G2AlertsSchema);

module.exports = G2Alerts;

这是我在mongodb网站上找到的代码。我只是想看看这个ID是否存在而已。基本上,当我获取新警报时,我会得到一个数组并对其进行迭代,我想根据数据库内的内容检查每个项目的 ID。如果存在,请跳过并转到下一个。如果是新的,则创建一个新警报并保存。

 const exists = await G2Alerts.aggregate([
    {
      $project: {
        exists: {
          $in: ['5f0b4f508bda3805754ab343', '$alertDetails._id'],
        },
      },
    },
  ]);

编辑:另一件事。我收到 eslint 警告,说我应该使用数组迭代而不是 for 循环。问题是,我在查找警报 ID 时需要使用等待。如果我使用、减少或过滤,我就不能使用等待。如果我在reduce或filter函数中使用async,那么它将返回promise或只是一个空数组。

以下内容有效,基于 Tom Slabbaert 提供的答案

  const newAlertsData = [];

  for (let item of alertData.data.items) {
    const exists = await G2Alerts.find({ 'alertDetails._id': `${item._id}` });
    if (exists.length === 0) {
      newAlertsData.push(item);
    }
  }

  if (newAlertsData.length !== 0) {......

但这并不

  const filteredAlerts = alertData.data.items.reduce((filtered, item) => {
    const exists = await G2Alerts.find({ 'alertDetails._id': `${item._id}` });
    if (exists.length === 0) {
      filtered.push(item);
    }
    return filtered;
  }, []);

enter image description here

最佳答案

你的想法并不遥远,下面是一个使用正确语法的示例:

const exists = await G2Alerts.findOne({"alertDetails._id": '5f0b4f508bda3805754ab343'}});
if (!exists) {
    ... do something
}

这也可以通过使用 aggregate$match 阶段而不是 $project 阶段来实现,甚至更好 countDocuments如果不需要,它只返回计数而不是整个对象。

我想补充的一件事是,确保 alertDetails._idstring 类型,因为您在中使用 string你是$in。否则你需要将它们转换为 mongoose 中的 ObjectId 类型,如下所示:

new mongoose.Types.ObjectId('5f0b4f508bda3805754ab343')

对于 Mongo:

import {ObjectId} from "mongodb"
...


new ObjectId('5f0b4f508bda3805754ab343')

编辑

尝试这样的事情吗?

let ids = alertData.data.items.map(item => item._id.toString());
let existing = await G2Alerts.distinct("alertsDetails._id", {"alertsDetails._id": {$in: ids}});

const filteredAlerts = alertData.data.items.reduce((filtered, item) => {
    if (!existing.includes(item._id.toString())) {
        return [item].concat(filtered)
    }
    return filtered;
}, []);

这样你只需要调用数据库一次,而不是多次。

基于提供的答案的最终代码。

  const ids = alertData.data.items.map(item => item._id);
  const existing = await G2Alerts.find({ 'alertDetails._id': { $in: ids } }).distinct(
    'alertDetails._id',
    (err, alerts) => {
      if (err) {
        res.send(err);
      }
      return alerts;
    },
  );

  const filteredAlerts = alertData.data.items.reduce((filtered, item) => {
    if (!existing.includes(item._id.toString()) && item.openDate > dateLimit) {
      return [item].concat(filtered);
    }
    return filtered;
  }, []);

关于javascript - mongoose 检查 id 是否存在,但该 id 嵌套在数组中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62878106/

相关文章:

javascript - 如何使用单个批处理文件或 javascript 导入或导出多个 mongo 集合

javascript - 如何在调用对象之前调用函数

java - 如何使用 Java 驱动程序抑制 mongodb 中的列?

javascript - Chrome 扩展程序内容脚本未注入(inject)特定网站

javascript - JavaScript 循环迭代中的 POST 之间需要延迟

javascript - 如何制作超过 5 个输入的松弛对话? Node 松弛API

javascript - 为 Node.JS + NPM 使用备用依赖项列表

mongodb - 正确的语法来执行 mongoDb docker 实例的 mongodump?

javascript - 当元素是通过 HTML 创建而不是通过 JavaScript 动态创建时,为什么我的 Popover 可以工作?

javascript - JavaScript 中可见性检查的测试条件