在MongoDB中,如何搜索子文档数组?

时间:2015-05-29 08:44:23

标签: java mongodb mongo-java

我在mongodb有一份调查文件,每项调查都有SELECT DATE(DATE_ADD(time, 5.75, 'HOUR')) AS day, ... FROM ... WHERE ... AND ( DATE_ADD(time, 5.75, "HOUR") >= '2015-05-01 00:00:00' AND DATE_ADD(time, 5.75, "HOUR") < '2015-06-01 00:00:00' ) GROUP EACH BY day ORDER BY day asc LIMIT 2000 的唯一身份证明。我无法理解如何在 surveyRefid = 377或360 的文档中查找 questionType = hard 的子文档。

以下是一份示例文件:

surveyRefId

编辑 - 根据Sylvain Leroux使用Java驱动程序解决方案

{
  "json": {
    "surveyRefId": 377,
    "surveyName": "survey on sociology",
    "questionsVoList": [
      {
        "questionId": "556708425215763c64b8af3d",
        "questionText": "question no 1",
        "questionTitle": "",
        "questionType": "hard",
        "preQuestion": true,
        "questionOptions": [
          {
            "questionRefId": 0,
            "optionType": "RADIOBUTTON",
            "isanswer": true,
            "optionText": "ch1"
          }
        ]
      },
      {
        "questionId": "556708425215763c64b8af3d",
        "questionText": "question no 2",
        "questionTitle": "",
        "questionType": "simple",
        "question": true,
        "questionOptions": [
          {
            "questionRefId": 0,
            "optionType": "RADIOBUTTON",
            "isanswer": true,
            "optionText": "ch1"
          }
        ],
      },
      {
       "questionId": "556708425215763c64b8af3d",
        "questionText": "question no 3",
        "questionTitle": "",
        "questionType": "hard",
        "questionOptions": [
          {
            "questionRefId": 0,
            "optionType": "RADIOBUTTON",
            "isanswer": true,
            "optionText": "ch1"
          },
          {
            "questionRefId": 0,
            "optionType": "RADIOBUTTON",
            "isanswer": false,
            "optionText": "ch2"
          }
        ],
       }
    ]
  }
}

1 个答案:

答案 0 :(得分:5)

“查找具有questionType = "hard"的子文档可以通过三种不同的方式理解:

所有文件都有“硬”查询

如果您只想所有文档都有“硬查询”,您将使用find$elemMatch

db.test.find({"json.surveyRefId": { $in: [377, 360]},
              "json.questionsVoList": {$elemMatch: {"questionType":"hard"}}})

首次“硬”查询文件

如果您需要找到文档的第一个“硬”查询,您可以将上述查询与$投影操作符结合使用:

db.test.find({"json.surveyRefId": { $in: [377, 360]}, 
              "json.questionsVoList": {$elemMatch: {"questionType":"hard"}}}
             {"json.surveyRefId":1, "json.questionsVoList.$":1})

所有硬查询

如果您需要查找文档的所有“硬”查询,则必须使用aggregation framework

db.test.aggregate({$match: { "json.surveyRefId": { $in: [377, 360]} }},
                  {$unwind: "$json.questionsVoList"},
                  {$match: { "json.questionsVoList.questionType": "hard"}},
                  {$group: {_id: "$_id", questionsVoList: {$push: "$json.questionsVoList"}}}
)
  • 第一个$match步骤将根据surveyRefId
  • 过滤掉不需要的文档
  • 然后$unwind将为每个子文档生成一份文档
  • 其他$match根据questionType
  • 过滤掉不需要的文件
  • 最后,$group会将所有子文档合并为一个给定的_id

产:

{
    "_id" : ObjectId("556828d002509ae174742d11"),
    "questionsVoList" : [
        {
            "questionId" : "556708425215763c64b8af3d",
            "questionText" : "question no 1",
            "questionTitle" : "",
            "questionType" : "hard",
            "preQuestion" : true,
            "questionOptions" : [
                {
                    "questionRefId" : 0,
                    "optionType" : "RADIOBUTTON",
                    "isanswer" : true,
                    "optionText" : "ch1"
                }
            ]
        },
        {
            "questionId" : "556708425215763c64b8af3d",
            "questionText" : "question no 3",
            "questionTitle" : "",
            "questionType" : "hard",
            "questionOptions" : [
                {
                    "questionRefId" : 0,
                    "optionType" : "RADIOBUTTON",
                    "isanswer" : true,
                    "optionText" : "ch1"
                },
                {
                    "questionRefId" : 0,
                    "optionType" : "RADIOBUTTON",
                    "isanswer" : false,
                    "optionText" : "ch2"
                }
            ]
        }
    ]
}