如何使用聚合从 mongodb 中的两个集合中查询?

Posted

技术标签:

【中文标题】如何使用聚合从 mongodb 中的两个集合中查询?【英文标题】:How to query from two collections in mongodb using aggregate? 【发布时间】: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) 【参考方案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 选项卡中进行测试

【讨论】:

以上是关于如何使用聚合从 mongodb 中的两个集合中查询?的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB - 聚合查询

MongoDB 聚合两个集合,返回附加字段作为计数

mongodb 如何把从一个集合中的查询结果 插入到一个新的集合

mongoDB表与表的关系及聚合管道查询

MongoDB聚合查询返回集合中每年每月的条目总数,按位置值分组

使用聚合 $lookup 加入 mongodb