在MongoDB中,如何在子文档数组中进行搜索?
In MongoDB, how do I search in an array of sub-documents?
我在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"
}
],
}
]
}
}
编辑-- 根据 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);
"find sub-documents having questionType = "hard"
"可以用三种不同的方式来理解:
所有文档 具有 "hard" 查询
如果您只希望 所有 个文档具有“硬查询”,您将使用 find
和 $elemMatch
:
db.test.find({"json.surveyRefId": { $in: [377, 360]},
"json.questionsVoList": {$elemMatch: {"questionType":"hard"}}})
第一个"hard"查询一个文档
如果你需要找到第一个"hard"一个文档的查询,你将上面的查询与$
投影运算符结合起来:
db.test.find({"json.surveyRefId": { $in: [377, 360]},
"json.questionsVoList": {$elemMatch: {"questionType":"hard"}}}
{"json.surveyRefId":1, "json.questionsVoList.$":1})
所有硬查询
如果您需要查找 所有 "hard" 文档的查询,您将不得不使用 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"
}
]
}
]
}
我在mongodb有一份调查文件,每份调查都有surveyRefId
作为唯一标识。我无法理解如何在 surveyRefid = 377 或 360.
这是一个示例文档:
{
"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"
}
],
}
]
}
}
编辑-- 根据 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);
"find sub-documents having questionType = "hard"
"可以用三种不同的方式来理解:
所有文档 具有 "hard" 查询
如果您只希望 所有 个文档具有“硬查询”,您将使用 find
和 $elemMatch
:
db.test.find({"json.surveyRefId": { $in: [377, 360]},
"json.questionsVoList": {$elemMatch: {"questionType":"hard"}}})
第一个"hard"查询一个文档
如果你需要找到第一个"hard"一个文档的查询,你将上面的查询与$
投影运算符结合起来:
db.test.find({"json.surveyRefId": { $in: [377, 360]},
"json.questionsVoList": {$elemMatch: {"questionType":"hard"}}}
{"json.surveyRefId":1, "json.questionsVoList.$":1})
所有硬查询
如果您需要查找 所有 "hard" 文档的查询,您将不得不使用 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"
}
]
}
]
}