簡體   English   中英

mongodb 聚合被字符串化並且不能在 nodejs 中工作

[英]mongodb aggregate gets stringified and does nto work in nodejs

我正在使用 mongodb 聚合,我能夠在 mongo shell 中編寫聚合並對其進行測試,它運行良好。 但是,當我嘗試在 Nodejs 方法中使其動態化並從前端傳遞值時,它什么也沒顯示。 我認為的原因是這個new ObjectId(YOUR ID IN STRING TYPE) 在我通過聚合執行 function 的那一刻,它會被觸發並且new ObjectId會被刪除,因此它不會被匹配。 這是我在 mongo shell 中編寫的工作匯總

db.ParcelStatus.aggregate([
  {
    $match: {
      $or: [
        {
          "statusRepositoryId": new ObjectId("5dd7fa20dcfa9600152cc2d8")
        },
        {
          "statusRepositoryId": new ObjectId("5dd7fa20dcfa9600152cc2dd")
        },
        {
          "createdAt": {
            "$gte": new Date("2020-05-01T18:59:59.001Z")
          }
        },
        {
          "createdAt": {
            "$lte": new Date("2020-05-31T18:59:59.099Z")
          }
        }
      ]
    }
  },
  {
    "$lookup": {
      "from": "Parcel",
      "localField": "parcelId",
      "foreignField": "_id",
      "as": "parcel"
    }
  },
  {
    "$unwind": {
      "path": "$parcel",
      "preserveNullAndEmptyArrays": true
    }
  },
  {
    "$lookup": {
      "from": "CustomerData",
      "localField": "parcel.customerDataId",
      "foreignField": "_id",
      "as": "parcel.customerData"
    }
  },
  {
    "$unwind": "$parcel.customerData"
  },
  {
    "$lookup": {
      "from": "Customer",
      "localField": "parcel.customerData.customerId",
      "foreignField": "_id",
      "as": "parcel.customerData.customer"
    }
  },
  {
    "$unwind": "$parcel.customerData.customer"
  },
  {
    "$lookup": {
      "from": "City",
      "localField": "parcel.customerData.cityId",
      "foreignField": "_id",
      "as": "parcel.customerData.city"
    }
  },
  {
    "$unwind": "$parcel.customerData.city"
  }
])

現在在 nodejs 中,這是我構建它的方式

 let pipeline = [];
  const matchObj = {
    $match: { $or: [] },
  };
  filters.forEach((obj) => {
    if (obj.key === "date") {
      matchObj.$match.$or.push(
        { createdAt: { $gte: new Date(obj.values.from) } },
        { createdAt: { $lte: new Date(obj.values.to) } }
      );
    }
    if (obj.key === "status_repository") {
      if (
        report.filters.find((x) => x.key === obj.key).selectionType === "single"
      ) {
        matchObj.$match.$or.push({
          statusRepositoryId: { $toObjectId: obj.values },
        });
      } else {
        obj.values.forEach((id) => {
          matchObj.$match.$or.push({ statusRepositoryId: { $toObjectId: id } });
        });
      }
    }
  });

  pipeline.push(matchObj);

  pipeline = [
    ...pipeline,
    {
      $lookup: {
        from: "Parcel",
        localField: "parcelId",
        foreignField: "_id",
        as: "parcel",
      },
    },
    {
      $unwind: {
        path: "$parcel",
        preserveNullAndEmptyArrays: true,
      },
    },
    {
      $lookup: {
        from: "CustomerData",
        localField: "parcel.customerDataId",
        foreignField: "_id",
        as: "parcel.customerData",
      },
    },
    { $unwind: "$parcel.customerData" },
    {
      $lookup: {
        from: "Customer",
        localField: "parcel.customerData.customerId",
        foreignField: "_id",
        as: "parcel.customerData.customer",
      },
    },
    { $unwind: "$parcel.customerData.customer" },
    {
      $lookup: {
        from: "City",
        localField: "parcel.customerData.cityId",
        foreignField: "_id",
        as: "parcel.customerData.city",
      },
    },
    {
      $unwind: "$parcel.customerData.city",
    },
  ];

在nodejs中,這就是它在控制台中的顯示方式

db.ParcelStatus.aggregate([
  {
    "$match": {
      "$or": [
        {
          "statusRepositoryId": "5dd7fa20dcfa9600152cc2d8"
        },
        {
          "statusRepositoryId":"5dd7fa20dcfa9600152cc2dd"
        },
        {
          "createdAt": {
            "$gte": "2020-05-01T18:59:59.001Z"
          }
        },
        {
          "createdAt": {
            "$lte": "2020-05-31T18:59:59.099Z"
          }
        }
      ]
    }
  },
  {
    "$lookup": {
      "from": "Parcel",
      "localField": "parcelId",
      "foreignField": "_id",
      "as": "parcel"
    }
  },
  {
    "$unwind": {
      "path": "$parcel",
      "preserveNullAndEmptyArrays": true
    }
  },
  {
    "$lookup": {
      "from": "CustomerData",
      "localField": "parcel.customerDataId",
      "foreignField": "_id",
      "as": "parcel.customerData"
    }
  },
  {
    "$unwind": "$parcel.customerData"
  },
  {
    "$lookup": {
      "from": "Customer",
      "localField": "parcel.customerData.customerId",
      "foreignField": "_id",
      "as": "parcel.customerData.customer"
    }
  },
  {
    "$unwind": "$parcel.customerData.customer"
  },
  {
    "$lookup": {
      "from": "City",
      "localField": "parcel.customerData.cityId",
      "foreignField": "_id",
      "as": "parcel.customerData.city"
    }
  },
  {
    "$unwind": "$parcel.customerData.city"
  }
])

請注意 nodejs 中的差異導致$matchnew Date(DATE)new ObjectId(ID) 如果您能告訴我如何解決此問題,我將不勝感激。

來自$match文檔:

$match 查詢語法與讀操作查詢語法相同; 即 $match 不接受原始聚合表達式。 要在 $match 中包含聚合表達式,請使用 $expr 查詢表達式:

什么是原始聚合表達式

表達式可以包括字段路徑、文字、系統變量、表達式對象和表達式運算符。 表達式可以嵌套。

在我們的上下文中$toObjectId是一個聚合表達式運算符,這意味着我們不能在$match使用它而不使用$expr ,如下所示:

db.collection.aggregate([
  {
    $match: {
      $expr: {
        $eq: [
          "$statusRepositoryId",
          {
            $toObjectId: "5dd7fa20dcfa9600152cc2d8"
          }
        ]
      }
    }
  }
])

蒙戈游樂場

這意味着您將不得不重新構建您的查詢,這可能會很煩人。 但我們確實有更好的解決方案,只需從 Mongo 導入ObjectId並在構造查詢時將字符串轉換為該字符串:

 if (obj.key === "status_repository") {
      if (
        report.filters.find((x) => x.key === obj.key).selectionType === "single"
      ) {
        matchObj.$match.$or.push({
          statusRepositoryId: new ObjectId(obj.values),
        });
      } else {
        obj.values.forEach((id) => {
          matchObj.$match.$or.push({ statusRepositoryId:  new ObjectId(id) });
        });
      }
    }

暫無
暫無

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

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