Mongodb选择特定元素形成嵌套文档

时间:2017-04-28 15:38:23

标签: mongodb mongodb-query spring-data-mongodb

我有以下MongoDB对象结构。我想根据值选择aclpermissions(使用Spring MogoTemplate)。例如如果我通过" 58dc0bea0cd182789fc62fab"它应该只返回aclpermissions.READ但是如果我通过" 58dc0bd70cd182789fc62faa"它应该返回所有的aclpermissions。

如何实现这一目标。如果我必须修改数据结构,请建议做什么以及如何实现。

{
        "_id" : ObjectId("5900d6abb9eb284a78f5a350"),
        "_class" : "com.debopam.amsapp.model.AMSAppACL",
        "attrUniqueCode" : "USER",
        "attributeVersion" : 1,
        "aclpermissions" : {
                "CRT" : [
                        "58dc0bd70cd182789fc62faa"
                ],
                "READ" : [
                        "58dc0bd70cd182789fc62faa",
                        "58dc0bea0cd182789fc62fab"
                ],
                "UPD" : [
                        "58dc0bd70cd182789fc62faa"
                ],
                "DLT" : [
                        "58dc0bd70cd182789fc62faa"
                ]
        },
        "orgHierachyIdentifier" : "14",
        "orgid" : 14,
        "createDate" : ISODate("2017-04-26T17:19:39.026Z"),
        "lastModifiedDate" : ISODate("2017-04-26T17:19:39.026Z"),
        "createdBy" : "appadmin",
        "lastModifiedBy" : "appadmin"
}

1 个答案:

答案 0 :(得分:1)

您可以使用Mongodb Search nested array elements

中相同的更新结构

您可以将$filter数组运算符与$setIsSubset查询运算符一起使用以下聚合查询,该运算符会比较并选择嵌套文档,其中输入值是aclpermission.v的子集。

 import static org.springframework.data.mongodb.core.aggregation.ArrayOperators.Filter.filter;
 import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
 import static java.util.Arrays.asList;

  Aggregation aggregation = newAggregation(
          match(Criteria.where("_id").is(new ObjectId("5900d6abb9eb284a78f5a350"))),
          project()
               .and(filter("aclpermissions")
                                .as("aclpermission")
                                .by(aggregationOperationContext -> new BasicDBObject("$setIsSubset", asList(asList("58dc0bd70cd182789fc62faa"), "$$aclpermission.v"))))
         .as("aclpermissions")
  );

 List<BasicDBObject> results = mongoTemplate.aggregate(aggregation, collectionName,  BasicDBObject.class).getMappedResults();

Mongo Shell查询:

aggregate([ { "$match" : { "_id" : ObjectId("5900d6abb9eb284a78f5a350")}} , { "$project" : { "aclpermissions" : { "$filter" : { "input" : "$aclpermissions" , "as" : "aclpermission" , "cond" : { "$setIsSubset" : [ ["58dc0bd70cd182789fc62faa"], "$$aclpermission.v"]}}}}}])

更新:

以下查询将$match attrUniqueCode值等于USER后跟$sort$group的{​​{1}}文档选择最新文档。 $$ROOT是表达式变量,用$first访问整个文档以获取最新文档。

 Aggregation aggregation = newAggregation(
         match(Criteria.where("attrUniqueCode").is("USER")),
         sort(new Sort(Sort.Direction.DESC, "attributeVersion")),
         group().first("$$ROOT").as("latest"),
         project("latest._id", "latest.attrUniqueCode", "latest.attributeVersion")
                        .and(filter("latest.aclpermissions")
                                .as("aclpermission")
                                .by(aggregationOperationContext -> new BasicDBObject("$setIsSubset", asList(asList("58dc0bd70cd182789fc62faa"), "$$aclpermission.v"))))
         .as("aclpermissions")
  );

参考

https://docs.mongodb.com/manual/reference/aggregation-variables/ https://docs.mongodb.com/manual/reference/operator/aggregation/project/ https://docs.mongodb.com/manual/reference/operator/aggregation/filter/