mongo复杂查询问题

原json

{
    "_id" : ObjectId("58b3a8dc96fbc7cfb8287093"),
    "name" : "《地下水质量标准》",
    "GBNumber" : "GB/T 14848-93",
    "dataEntryClerk" : "handsomeboy",
    "lastModified" : "Fri Feb 27 2017 12:03:40 GMT+0800",
    "contents" : [ 
        {
            "standardID" : "9527-01",
            "unit" : "mg/L",
            "classifications" : [ 
                {
                    "level" : "I",
                    "upperLimit" : "0",
                    "lowerLimit" : "50"
                }, 
                {
                    "level" : "II",
                    "upperLimit" : "50",
                    "lowerLimit" : "150"
                }, 
                {
                    "level" : "III",
                    "upperLimit" : "150",
                    "lowerLimit" : "250"
                }, 
                {
                    "level" : "IV",
                    "upperLimit" : "250",
                    "lowerLimit" : "350"
                }, 
                {
                    "level" : "V",
                    "upperLimit" : "350",
                    "lowerLimit" : "-1"
                }
            ]
        }, 
        {
            "standardID" : "7439-89-6",
            "unit" : "mg/L",
            "classifications" : [ 
                {
                    "level" : "I",
                    "upperLimit" : "0",
                    "lowerLimit" : "0.1"
                }, 
                {
                    "level" : "II",
                    "upperLimit" : "0.1",
                    "lowerLimit" : "0.2"
                }, 
                {
                    "level" : "III",
                    "upperLimit" : "0.2",
                    "lowerLimit" : "0.3"
                }, 
                {
                    "level" : "IV",
                    "upperLimit" : "0.3",
                    "lowerLimit" : "0.4"
                }, 
                {
                    "level" : "V",
                    "upperLimit" : "0.5",
                    "lowerLimit" : "-1"
                }
            ]
        }
    ]
}

想查询出来的结果:

{
    "contents" : [ 
        {
            "standardID" : "9527-01",
            "unit" : "mg/L",
            "classifications" : [ 
                {
                    "level" : "I",
                    "upperLimit" : "0",
                    "lowerLimit" : "50"
                }, 
                {
                    "level" : "II",
                    "upperLimit" : "50",
                    "lowerLimit" : "150"
                }, 
                {
                    "level" : "III",
                    "upperLimit" : "150",
                    "lowerLimit" : "250"
                }, 
                {
                    "level" : "IV",
                    "upperLimit" : "250",
                    "lowerLimit" : "350"
                }, 
                {
                    "level" : "V",
                    "upperLimit" : "350",
                    "lowerLimit" : "-1"
                }
            ]
        }
    ]
}

请问下各位大牛db.xxx.find() 该怎么写呢

阅读 2.5k
评论
    4 个回答

    先提个意见:

    提问题,把最小化可复现问题的例子放出来就好,你这放这么长一文档,大家看的很累。


    你需要的其实是返回数组中某些特定文档,而不是整个数组。

    1 如果你只需要返回数组中的一个元素

    db.xxx.find(
        {'contents.standardID': '9527-01'},
        {contents: {$elemMatch: {standardID: '9527-01'}}, _id: 0}
    )
    

    第一行是查询条件,第二行是过滤条件。 可以看到操作符也可以用在过滤条件里面。但是这个操作符只会返回满足条件的第一个元素,并且需要2.2版本以上的MongoDB。

    或者使用$下标选择符:

    db.xxx.find(
        {'contents.standardID': '9527-01'},
        {'contents.$': 1, _id: 0}
    )
    

    上面例子中的查询条件也可以使用$elemMatch

    如果你需要返回数组中多个匹配的元素:

    2 $unwind

    通过把$unwind来把contents作为一个独立的文档流来进行操作,代码见@bguo的回答。
    但是如果你的数组很大,这会导致性能问题。

    3 $filter

    这是一个3.2版本中新出的操作符,用来过滤返回的内容。

    db.xxx.aggregate(
        {$match: {'contents.standardID': '9527-01'}},
        {$project: {
            contents: {$filter: {
                input: '$contents',
                as: 'contents',
                cond: {$eq: ['$$contents.standardID', '9527-01']}
            }},
            _id: 0
        }}
    )
    

    当然你还可以使用$redact(2.6版本), 或者mapReduce()等等多种方法。

      • 745

      查询条件。比如 name

      db.xxx.find({"name" : "《地下水质量标准》" } ,function(err, data){ 
          if(data){
              console.log(data.contents)
          }
      })
        • 1.7k

        一种实现方法:利用MongoDB的Aggregate。

        1、先对包含array的contents施加$unwind

        2、然后利用$match,施加过滤条件

        3、最后利用$project,保留所需的field

        参考下方的代码

         db.test1.aggregate([
                            {$unwind : "$contents"},
                            {$match : { name :  "《地下水质量标准》", "contents.standardID" :  "9527-01"}},
                            { $project : { contents : 1 , _id : 0 }}
                            ])

        供参考。

        Love MongoDB! Have Fun!

        ------------------------华丽的分割符--------------------------------

        MongoDB中文社区线下活动缤纷,请猛戳下方:

        2017华山论剑|MongoDB中文社区

        三月份杭州站在即!!! 感兴趣的朋友火速报名!!!

          db.xxx.find({"contents.standardID": "9527-01"}, {contents: 1})
          
          _id字段会自动输出,就忽略吧
            撰写回答

            登录后参与交流、获取后续更新提醒

            相似问题
            MongoDB 技术问答
            合作问答

            MongoDB 官方中文社区 和 SegmentFault 联合推出的 MongoDB 技术交流平台。 这是一个以社区力量为主,但...

            推荐文章