0

I have below MongoDB object structure. I would like to select aclpermissions based on values (using Spring MogoTemplate). e.g. if I pass "58dc0bea0cd182789fc62fab" it should return only aclpermissions.READ but if I pass "58dc0bd70cd182789fc62faa" it should return all the aclpermissions.

How to achieve that. if I have to modify data structure please suggests what to do and how to achieve that.

{
        "_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 Answer 1

1

You can use the same updated structure from Mongodb Search nested array elements

You can use the below aggregation query with $filter array operator with $setIsSubset query operator, which compares and selects the nested document where input value is a subset of 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 query:

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

Update:

The below query will $match documents with attrUniqueCode value equal to USER followed by $sort and $group the pick the latest document. $$ROOT is expression variable to access the whole document with $first to get the latest one.

 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")
  );

Reference

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/

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks. Will test this and let you know.
This works. but as I asked in stackoverflow.com/questions/43667611/… could you please let know how to integrate that. Considering for a "attrUniqueCode" there can be multiple "attributeVersion". How to select latest one i.e. record with the highest version.
You are welcome. Updated to include the filter from the other post. See if it helps.
Thanks it worked. But could you please explain to me what is happening here. $$ROOT, Project and filter etc.
You are welcome. Add some more description and links

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.