如何获取另一个嵌套文档列表的嵌套记录?

时间:2017-07-19 11:25:36

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

我在检索另一个嵌套列表的嵌套文档对象时遇到了困难。请帮我解决一下。我的mongoDB文件如下:

{ 
"_id" : "PT5", 
"departmentId" : "DEPT5", 
"subDepartmentList" : [
    {
        "subDepartmentId" : "SUBDEPT19", 
        "subDepartmentName" : "X-Ray",  
        "labServiceList" : [
            {
                "_id" : "123abc", 
                "subDepartmentId" : "SUBDEPT19", 
                "labServiceName" : "serviceOne"
            }, 
            { 
                "_id" : "123def", 
                "subDepartmentId" : "SUBDEPT19", 
                "labServiceName" : "hello", 
                }
        ]
    }, 
    {
        "subDepartmentId" : "SUBDEPT21", 
        "subDepartmentName" : "Haemotology",
        "labServiceList" : [
            {
                "_id" : "456abc", 
                "subDepartmentId" : "SUBDEPT21", 
                "labServiceName" : "abcd", 
                }
        ]
    }
]

}

从上面的文档中我想通过使用其_id值来检索labServiceList的一个对象(在本文档中为Ex:“_ id”:“123abc”)。除了匹配的嵌套文档之外,我不想获得任何其他字段。我尝试过以下查询:

db.labServiceMasters.aggregate([
{"$project": {
    "subDepartmentList": {"$filter": {
        "input": '$subDepartmentList.labServiceList',
        "as": 'labServiceList',
        "cond": {"$eq": ['$$labServiceList._id', '123abc']}
    }},
    "_id": 0
}}

])

我也试过使用$ map运算符,但没有任何事情妨碍我。请帮我解决这个问题。还请帮我用Java中的mongoTemplate编写相同的查询。任何建议都会很明显。在此先感谢: - )

1 个答案:

答案 0 :(得分:1)

您实际上需要在$map内嵌套$filter,在$filter内嵌套$map。并使用$arrayElemAt获取单个条目:

db.labServiceMasters.aggregate([
  { "$project": {
    "subDepartmentList": {
      "$arrayElemAt": [
        { "$filter": {
          "input": {
            "$map": {
              "input": "$subDepartmentList",
              "as": "sd",
              "in": {
                "$arrayElemAt": [
                  { "$filter": {
                    "input": "$$sd.labServiceList",
                    "as": "ls",
                    "cond": { "$eq": [ "$$ls._id", "123abc" ] }
                  }},
                  0
                ]  
              }
            }
          },
          "as": "sd",
          "cond": { "$ne": [ "$$sd", null ] }
        }},
        0
      ]
    }  
  }}
])

返回:

{
    "_id" : "PT5",
    "subDepartmentList" : {
        "_id" : "123abc",
        "subDepartmentId" : "SUBDEPT19",
        "labServiceName" : "serviceOne"
    }
}

对于spring-mongodb来说:

    Aggregation aggregation = newAggregation(
      project("subDepartmentList").and(new AggregationExpression() {
          @Override
          public DBObject toDbObject(AggregationOperationContext context) {
              return new BasicDBObject(
                "$arrayElemAt", Arrays.asList(
                  new BasicDBObject("$filter",
                    new BasicDBObject("input",
                      new BasicDBObject("$map",
                        new BasicDBObject("input","$subDepartmentList")
                          .append("as","sd")
                          .append("in",new BasicDBObject(
                            "$arrayElemAt", Arrays.asList(
                              new BasicDBObject("$filter",
                                new BasicDBObject("input","$$sd.labServiceList")
                                  .append("as","ls")
                                  .append("cond", new BasicDBObject("$eq", Arrays.asList("$$ls._id","123abc")))
                              ),
                              0
                            )
                          ))
                      )
                    )
                    .append("as","sd")
                    .append("$ne", Arrays.asList("$$sd", null))
                  ),
                  0
                )
              );
          }
      }).as("subDepartmentList")
    );

序列化相同:

{
  "aggregate": "labServiceMasters",
  "pipeline": [
    {
      "$project": {
        "subDepartmentList": {
          "$arrayElemAt": [
            {
              "$filter": {
                "input": {
                  "$map": {
                    "input": "$subDepartmentList",
                    "as": "sd",
                    "in": {
                      "$arrayElemAt": [
                        {
                          "$filter": {
                            "input": "$$sd.labServiceList",
                            "as": "ls",
                            "cond": {
                              "$eq": [
                                "$$ls._id",
                                "123abc"
                              ]
                            }
                          }
                        },
                        0.0
                      ]
                    }
                  }
                },
                "as": "sd",
                "$ne": [
                  "$$sd",
                  null
                ]
              }
            },
            0.0
          ]
        }
      }
    }
  ]
}