【问题标题】:MongoDB lookup and filter by foreign documentsMongoDB 按外部文档查找和过滤
【发布时间】:2021-09-20 21:30:18
【问题描述】:

我有user 集合,其中包含具有roleId 的角色对象。我也有 roles 有 id 的集合。 现在,对于每个角色,我想获取用户列表。

例如:

[
    {
        "name": "Scott",
        "isActive": true,
        "role": {
            "roleId": "123432"
        }
    },
    {
        "name": "John",
        "isActive": true,
        "role": {
            "roleId": "123432"
        }
    },
    {
        "name": "Scott",
        "isActive": true,
        "role": {
            "roleId": "556432"
        }
    }
]

角色数据:

[
    {
        "id": "123432"
        "name": "admin",
        "type": "internal"
    },
    {
        "id": "556432"
        "name": "owner",
        "type": "external"
    },
    {
        "id": "556432"
        "name": "owner",
        "type": "internal"
    } 
]

现在我想获取internal 类型的所有角色及其相关用户:

所以,输出应该是,

[
    {
       "role": "123432",
        "users": [
            {
                "name": "Scott",
                "role": {
                    "roleId": "123432"
                }
            },
            {
                "name": "John",
                "role": {
                    "roleId": "123432"
                }
            }
        ],
        { 
            "role": "556432",
            "users": []
         }
    }
]

这是我在 SpringBoort 中的聚合:

LookupOperation lookupOperation = LookupOperation.newLookup().from("roles").localField("roleId")
                .foreignField("_id").as("roles");

        AggregationOperation match = Aggregation.match(Criteria.where("type").is("internal"));

        Aggregation aggregation = Aggregation.newAggregation(lookupOperation, match);

        List<UserDTO> results = mongoTemplate.aggregate(aggregation, "users", UserDTO.class).getMappedResults();

但这不起作用。匹配过滤器与主表(用户)字段一起使用。但它不适用于外国收藏(角色)

有人可以帮我解决这个问题吗?

【问题讨论】:

    标签: mongodb aggregation-framework spring-data-mongodb


    【解决方案1】:

    AggregationOperation isActiveMatch= Aggregation.match(Criteria.where("isActive").is(true)); 应该是第一场比赛。

    LookupOperation lookupOperation = LookupOperation.newLookup().from("roles").localField("roleId")
                    .foreignField("_id").as("roles");
    
    AggregationOperation match = Aggregation.match(Criteria.where("type").is("internal"));
    
    Aggregation aggregation = Aggregation.newAggregation(isActiveMatch,lookupOperation, match);
    

    更新 1

    你可能会这样,

    db.user.aggregate([
      {
        "$lookup": {
          "from": "roles",
          "localField": "role.roleId",
          "foreignField": "id",
          "as": "roles"
        }
      },
      {
        $project: {
          roles: {
            "$filter": {
              "input": "$roles",
              "cond": {
                $eq: [
                  "$$this.type",
                  "internal"
                ]
              }
            }
          }
        }
      },
      {
        $match: {
          roles: {
            $ne: []
          }
        }
      }
    ])
    

    工作Mongo playground

    这里需要在lookup之后添加两个stage。第一个是过滤区间,第二个是消除空角色数组。

    ProjectionOperation as =
            project()
                .and(
                    ArrayOperators.Filter.filter("roles")
                        .as("role")
                        .by(ComparisonOperators.Eq.valueOf("role.type").equalTo("interval")))
                .as("roles");
    

    我已经添加了项目阶段,希望您可以添加匹配阶段。以上代码未经测试,是根据工作脚本编写的。

    【讨论】:

    • 对不起@varman。可能是我没有正确地问我的问题。更新了我的问题。我只需要根据来自外国收藏的属性过滤记录
    猜你喜欢
    • 2016-12-19
    • 1970-01-01
    • 2016-08-29
    • 2015-05-03
    • 2021-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-20
    相关资源
    最近更新 更多