簡體   English   中英

mongoose 檢查 id 是否存在但該 id 嵌套在數組中

[英]mongoose check if id exists but that id is nested inside an array

當我獲取新警報時,我想檢查新警報的 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。 如果它在那里,跳過和 go 到下一個。 如果它是新的,則創建一個新警報並保存它。

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

編輯:另一件事。 我收到一個 eslint 警告,說我應該使用數組迭代而不是 for 循環。 問題是,我需要在查找警報 ID 時使用 await。 如果我使用、減少或過濾,我不能使用等待。 如果我在 reduce 或過濾器 function 中使用異步,那么它將返回 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;
  }, []);

在此處輸入圖像描述

離你不遠了,這里有一個使用正確語法的例子:

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

這也可以使用帶有$match階段而不是$project階段的aggregate來實現,或者甚至更好的countDocuments如果您不需要它,它只返回計數而不是整個 object。

我想補充的另一件事是確保alertDetails._idstring類型,因為您在$in使用string 否則,您需要將它們轉換為 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;
  }, []);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM