问题
I have below document structure.
{
"_id" : { "teacherId" : "<teacherId>", "Year" : "<Year>" },
"groups" : [ {
"groupId" : "<uuid>",
"groupName" : "<name>",
"groupNameLowerCase" : "<name_in_lower_case>",
"description" : "<desc>",
"students" : ["<studentid1>", "<studentid2>", ...],
"editedDate" : "<currentTimestamp>"
},
...
],
"editedDate" : "<currentTimestamp>",
"points" : "<points>"
}
Consider that below two documents are present in DB
{
"_id" : { "teacherId" : "1", "Year" : "2016" },
"groups" : [ {
"groupId" : "123",
"groupName" : "Test1",
"groupNameLowerCase" : "test1",
"description" : "sample document",
"students" : ["11", "22"]
},
{
"groupId" : "234",
"groupName" : "Test2",
"groupNameLowerCase" : "test2",
"description" : "sample document",
"students" : ["11", "22"]
},
{
"groupId" : "345",
"groupName" : "Test3",
"groupNameLowerCase" : "test3",
"description" : "sample document",
"students" : ["21", "32"]
}
],
"points" : "650"
}
{
"_id" : { "teacherId" : "1", "Year" : "2015" },
"groups" : [ {
"groupId" : "123",
"groupName" : "HOCKEY",
"groupNameLowerCase" : "HOCKEY",
"description" : "HOCKEY team",
"students" : ["11", "22"]
},
{
"groupId" : "234",
"groupName" : "football",
"groupNameLowerCase" : "football",
"description" : "sample football",
"students" : ["11", "22"]
},
{
"groupId" : "345",
"groupName" : "Test3",
"groupNameLowerCase" : "test3",
"description" : "sample document",
"students" : ["21", "32"]
}
],
"points" : "650"
I want to select groups for the specified student and teacher combination. e.g. If I supply teacherid= 1 and student id =11 then query should return two documents with matching groups. I wrote below code to get the matching groups in document. But afterward I understand that elemMatch will only return first element matching. It will return two documents but with only one group in it.
Here I would like to understand the options available in Mongodb 2.4 to filter arrays in document returned by some query.
String teacherId = "1";
String studentId = "11";
Criteria documentSearchCriteria = where("_id.teacherId").is(teacherId)
.and("groups")
.elemMatch(where("students").in(studentId));
Criteria groupFilterCriteria = where("groups").elemMatch(where("students").in(studentBid));
BasicQuery query = new BasicQuery(documentSearchCriteria.getCriteriaObject(), groupFilterCriteria.getCriteriaObject());
List<GroupsDocument> groupsDocumentList = groupsMongoTemplate.find(query, GroupsDocument.class);
回答1:
As you said elemMatch will retrieve only first object in an array so you have to use aggregate future to achieve your output
MatchOperation match = Aggregation.match(Criteria.where("_id.teacherId").is("1").and("groups.students").in(11));
UnwindOperation unwind = Aggregation.unwind("groups");
GroupOperation group = Aggregation.group("_id").push("groups").as("groups").first("points").as("points");
Aggregation aggregation = Aggregation.newAggregation(unwind, match, group);
AggregationResults<BasicDBObject> groupResults = mongoTemplate.aggregate(aggregation,
CustomGroupsDocument.class, BasicDBObject.class);
List<BasicDBObject> result = groupResults.getMappedResults();
来源:https://stackoverflow.com/questions/40625566/how-to-filter-array-in-mongodb-document-using-spring