java - 在 MongoDB 中,如何在子文档数组中进行搜索?

标签 java mongodb mongo-java

我在mongodb中有一份调查文件,每份调查都有surveyRefId作为唯一标识。我无法理解如何在 surveyRefid = 377 或 360 的文档中找到具有 questionType = hard 的子文档。

这是一个示例文档:

{
  "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"
          }
        ],
       }
    ]
  }
}

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

    BasicDBObject matchSurvey = new BasicDBObject();
    matchSurvey.put("$match", new BasicDBObject("json.surveyRefId", new BasicDBObject("$in", new Integer[]{377,360})));
    BasicDBObject unwind = new BasicDBObject();
    unwind.put("$unwind", "$json.questionsVoList");
    BasicDBObject matchQuestion = new BasicDBObject();
    matchQuestion.put("$match", new BasicDBObject("json.questionsVoList.questionType", "hard"));
    HashMap map = new HashMap();
    map.put("_id", "$_id");
    map.put("questionsVoList", new BasicDBObject("$push", "$json.questionsVoList"));
    BasicDBObject group = new BasicDBObject();
    group.put("$group",map);        
    List<BasicDBObject> list = new ArrayList<BasicDBObject>();
    list.add(matchSurvey);
    list.add(unwind);
    list.add(matchQuestion);
    list.add(group);
    AggregateIterable output = collection.aggregate(list, DBObject.class);

最佳答案

“查找具有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"
                }
            ]
        }
    ]
}

关于java - 在 MongoDB 中,如何在子文档数组中进行搜索?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30525084/

相关文章:

java - MongoDB Java API 读取速度慢

java - Spring 在运行时添加外部 spring 上下文

java - Chrome 和 JNLP 发布

mysql - MongoDB 读/写锁

MongoDB,如何合并两个或多个数据库

java - 为什么 mongo-java-driver 不存在 eq?

mongodb - MongoException : java. lang.OutOfMemoryError:超出了GC开销限制

java - 在 Spring Boot Angular 8 Web 应用程序中验证和管理用户的最简单方法是什么?

java - Tomcat 上的 JSF - 为什么这可能?

node.js - Mongoose,express-使用对象数组创建模式