繁体   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