Mongoose 聚合:基于 Model.associated_Model.associated_Model.field 过滤返回错误结果

Posted

技术标签:

【中文标题】Mongoose 聚合:基于 Model.associated_Model.associated_Model.field 过滤返回错误结果【英文标题】:Mongoose aggregate: Filtering based on Model.associated_Model.associated_Model.field returns wrong result 【发布时间】:2021-06-11 21:33:56 【问题描述】:

我有三个模型UserProfileInstitution

用户

const UserSchema = new Schema(
  name: 
    type: Schema.Types.String,
  ,
  profile: 
    type: Schema.Types.ObjectId,
    ref: "profiles",
  ,
);

简介

const ProfileSchema = new Schema(
  institution: 
    type: Schema.Types.ObjectId,
    ref: "institutions",
  ,
);

机构

const InstitutionSchema = new Schema(
  name: 
    type: String,
    required: true,
  ,
);

我正在尝试获取用户列表WHERE机构=机构名称:

User.aggregate([
    
      $lookup: 
        from: "profiles",
        let:  profiles_id: "$profile" ,
        pipeline: [
          
            $lookup: 
              from: "institutions",
              pipeline: [
                
                  $match:  name: institution_name ,
                ,
              ],
              as: "institution",
            ,
          ,
           $unwind: "$institution" ,
        ],
        as: "profile",
      ,
    ,
     $unwind: "$profile" ,
    
      $project: 
        name: "$name",
        institution: "$profile.institution.name",
      ,
    ,
  ]);

出于某种奇怪的原因,这是返回所有用户的列表,但它用我使用的过滤器值替换机构字段institution_name。 知道如何解决这个问题吗?

【问题讨论】:

你的预期输出是什么? 【参考方案1】:

您的查询中的主要错误是您没有根据某些条件执行连接。在第一个$lookupprofiles 集合中,您将profile 作为profiles_id 传递,但未在管道中使用它。第二个$lookupinstitutions 的情况也是如此。

试试这个:

const institution_name = "Institute 1";

db.users.aggregate([
    
        $lookup: 
            from: "profiles",
            let:  profiles_id: "$profile" ,
            pipeline: [
                
                    $match: 
                        // Join condition.
                        $expr:  $eq: ["$_id", "$$profiles_id"] 
                    
                ,
                
                    $lookup: 
                        from: "institutions",
                        let:  institution_id: "$institution" ,
                        pipeline: [
                            
                                $match: 
                                    name: institution_name,
                                    // Join condition.
                                    $expr:  $eq: ["$_id", "$$institution_id"] 
                                
                            
                        ],
                        as: "institution"
                    
                ,
                 $unwind: "$institution" ,
            ],
            as: "profile",
        
    ,
     $unwind: "$profile" ,
    
        $project: 
            name: "$name",
            institution: "$profile.institution.name"
        
    
]);

输出:

/* 1 createdAt:3/13/2021, 6:19:07 PM*/

    "_id" : ObjectId("604cb4c36b2dcb17e8b152b8"),
    "name" : "Dheemanth Bhat",
    "institution" : "Institute 1"
,

/* 2 createdAt:3/13/2021, 6:19:07 PM*/

    "_id" : ObjectId("604cb4c36b2dcb17e8b152b9"),
    "name" : "Ahmed Ghrib",
    "institution" : "Institute 1"

测试数据:

users收藏:

/* 1 createdAt:3/13/2021, 6:19:07 PM*/

    "_id" : ObjectId("604cb4c36b2dcb17e8b152b8"),
    "name" : "Dheemanth Bhat",
    "profile" : ObjectId("604cb4b16b2dcb17e8b152b5")
,

/* 2 createdAt:3/13/2021, 6:19:07 PM*/

    "_id" : ObjectId("604cb4c36b2dcb17e8b152b9"),
    "name" : "Ahmed Ghrib",
    "profile" : ObjectId("604cb4b16b2dcb17e8b152b6")
,

/* 3 createdAt:3/13/2021, 6:19:07 PM*/

    "_id" : ObjectId("604cb4c36b2dcb17e8b152ba"),
    "name" : "Alex Rider",
    "profile" : ObjectId("604cb4b16b2dcb17e8b152b7")

profiles收藏:

/* 1 createdAt:3/13/2021, 6:18:49 PM*/

    "_id" : ObjectId("604cb4b16b2dcb17e8b152b5"),
    "institution" : ObjectId("604cb49a6b2dcb17e8b152b2")
,

/* 2 createdAt:3/13/2021, 6:18:49 PM*/

    "_id" : ObjectId("604cb4b16b2dcb17e8b152b6"),
    "institution" : ObjectId("604cb49a6b2dcb17e8b152b2")
,

/* 3 createdAt:3/13/2021, 6:18:49 PM*/

    "_id" : ObjectId("604cb4b16b2dcb17e8b152b7"),
    "institution" : ObjectId("604cb49a6b2dcb17e8b152b3")
,

/* 4 createdAt:3/13/2021, 6:18:49 PM*/

    "_id" : ObjectId("604cb4b16b2dcb17e8b152b8"),
    "institution" : ObjectId("604cb49a6b2dcb17e8b152b4")

institutions收藏:

/* 1 createdAt:3/13/2021, 6:18:26 PM*/

    "_id" : ObjectId("604cb49a6b2dcb17e8b152b2"),
    "name" : "Institute 1"
,

/* 2 createdAt:3/13/2021, 6:18:26 PM*/

    "_id" : ObjectId("604cb49a6b2dcb17e8b152b3"),
    "name" : "Institute 2"
,

/* 3 createdAt:3/13/2021, 6:18:26 PM*/

    "_id" : ObjectId("604cb49a6b2dcb17e8b152b4"),
    "name" : "Institute 3"

【讨论】:

以上是关于Mongoose 聚合:基于 Model.associated_Model.associated_Model.field 过滤返回错误结果的主要内容,如果未能解决你的问题,请参考以下文章

[第16期] mongoDB 干货笔记(mongoose/增删改查/聚合/索引/连接/备份与恢复/监控等)

Mongoose 虚拟填充和聚合

Mongoose 聚合 $match 返回空结果

Mongoose,使用 $lookup 的聚合查询返回 null?

Express + Mongoose + 聚合 + 计算可用库存

MongoDB 聚合与 Mongoose 虚拟