【问题标题】:How to query from two collections in mongodb using aggregate?如何使用聚合从 mongodb 中的两个集合中查询?
【发布时间】:2020-09-19 05:09:52
【问题描述】:

我的 mongoDB 中有以下两个集合:

产品:

[
    {
        "_id": "5ebb0984e95e3e9e35aab3bf",
        "name": "Product 1",
        "brand": "ABC",
        "code": "7891910000190",
        "description": "Lorem Ipsum"
    },
    {
        "_id": "5ebdb9f3d943ae000a4a9714",
        "name": "Product 2",
        "brand": "DEF",
        "code": "7891910000190",
        "description": "Lorem Ipsum"
    }
]

库存商品:

[
    {
        "_id": "5ed0586b7f2cfe02387d0706",
        "companyId": "5ed0491bf9a892a5fd9b4d9b",
        "branchId": "5ed049a8f9a892a5fd9b4d9e",
        "inventoryId": "5ed04d01e9e43cee79734b95",
        "productId": "5ebb0984e95e3e9e35aab3bf"
    },
    {
        "_id": "5ed058da75e4e01013f5779d",
        "companyId": "5ed0491bf9a892a5fd9b4d9b",
        "branchId": "5ed049a8f9a892a5fd9b4d9e",
        "inventoryId": "5ed04cede9e43cee79734b93",
        "productId": "5ebb0984e95e3e9e35aab3bf"
    },
    {
        "_id": "5ed059483da3bafccb34cec3",
        "companyId": "5ed0491bf9a892a5fd9b4d9b",
        "branchId": "5ed049a8f9a892a5fd9b4d9e",
        "inventoryId": "5ed04d01e9e43cee79734b95",
        "productId": "5ebb0984e95e3e9e35aab3bf"
    }
]

我想得到以下结果:

[
    {
        "_id": "5ed0586b7f2cfe02387d0706",
        "data": {
            "_id": "5ebb0984e95e3e9e35aab3bf",
            "brand": "ABC",
            "code": "7891910000190",
            "description": "Lorem Ipsum",
            "name": "Product 1",
        }
    },
    {
        "_id": "5ed059483da3bafccb34cec3",
        "data": {
            "_id": "5ebb0984e95e3e9e35aab3bf",
            "brand": "ABC",
            "code": "7891910000190",
            "description": "Lorem Ipsum",
            "name": "Product 1",
        }
    }
]

我的 NodeJS 和 MongoDB 聚合如下所示:

const mongoose = require("mongoose");
const StockGoods = mongoose.model("StockGoods");
ObjectId = require("mongodb").ObjectID;

exports.getProducts = async (companyId, branchId, inventoryId) => {
  const response = await StockGoods.aggregate([
    {
      $match: {
        companyId: new ObjectId("5ed0491bf9a892a5fd9b4d9b"), // new ObjectId(companyId)
        inventoryId: new ObjectId("5ed04d01e9e43cee79734b95"), // new ObjectId(inventoryId)
        branchId: new ObjectId("5ed049a8f9a892a5fd9b4d9e"), // new ObjectId(branchId)
      },
    },
    {
      $lookup: {
        from: "products",
        localField: "productId",
        foreignField: "_id",
        as: "inventory_docs",
      },
    },
    {
      $project: {
        data: "$inventory_docs",
      },
    },
    { $unwind: "$data" },
  ]);
  return response;
};

这是同一个数据库和上面描述的聚合函数,你可以检查这个:https://mongoplayground.net/p/FRgAIfO2bwh

但是,当我使用 nodejs 时,这个函数聚合不起作用。 我的 API 不返回任何内容(空数组)。

怎么了?

【问题讨论】:

  • 欢迎来到 SO。这不是 MongoDB 的工作方式。您提供的语法是 SQL。链接:docs.mongodb.com/manual/tutorial
  • 嗨@DzenisH。 ,我包括了我的 mongoDB 聚合,但这不起作用。你能帮帮我吗?
  • 可能是您的 $match 检查它们是否是 ObjectID,顺便说一下,您应该在 $lookup 之前进行 $match
  • @Koodies 我更新了我的代码,但它仍然无法正常工作:(
  • 您是否检查过 $match: { companyId: "5ed0491bf9a892a5fd9b4d9b", inventoryId: "5ed04d01e9e43cee79734b95", branchId: "5ed049a8f9a892a5fd9b4d9e", }, 是 ObjectID("5ed0491bf9a892a5fd9a48f)

标签: node.js mongodb mongoose aggregation-framework


【解决方案1】:

[已解决]

问题出在方案中:

companyId: {
    type: String,
    required: true,
},

正确的是:

companyId: {
    type: Schema.Types.ObjectId,
    required: true,
},

【讨论】:

    【解决方案2】:

    这里的问题是您在集合中存储数据的方式...... StockGoods 集合具有 companyId、inventoryId 和 branchId 作为字符串,但聚合正在寻找符合条件的 ObjectId aee:

     $match: {
        companyId: new ObjectId("5ed0491bf9a892a5fd9b4d9b"), // new ObjectId(companyId)
        inventoryId: new ObjectId("5ed04d01e9e43cee79734b95"), // new 
        ObjectId(inventoryId)
        branchId: new ObjectId("5ed049a8f9a892a5fd9b4d9e"), // new ObjectId(branchId)
      },
    

    根据您存储在数据库中的数据,您需要使用字符串更新匹配项。

    所以下面的聚合对你有用..

    [
     {
      "$match": {
         "companyId": "5ed0491bf9a892a5fd9b4d9b",
         "inventoryId": "5ed04d01e9e43cee79734b95",
         "branchId": "5ed049a8f9a892a5fd9b4d9e"
      }
      },
     {
      "$lookup": {
         "from": "products",
         "localField": "productId",
         "foreignField": "_id",
         "as": "inventory_docs"
      }
      },
     {
      "$project": {
         "data": "$inventory_docs"
      }
     },
    {
      "$unwind": "$data"
    }
    

    ]

    您可以在 Compass Aggregator 选项卡中进行测试

    【讨论】:

      猜你喜欢
      • 2023-03-28
      • 1970-01-01
      • 2017-07-13
      • 1970-01-01
      • 2020-01-31
      • 1970-01-01
      • 2020-03-24
      • 2014-02-23
      • 2016-09-27
      相关资源
      最近更新 更多