Reputation: 915
I have a Educational Intitution document which seems like this:
{
name: ...,
addresses: [...],
courses: [ {name: ... , duration: ..., tags[...]} ]
}
tags has an String array.
I am trying find a course which has some tags inside, like: java, eclipse, struts and so on...
My search method looks like this:
public BasicDBList coordinates(List tags){
BasicDBObject cmdBody = new BasicDBObject("aggregate", "EducationalInstitution");
List<BasicDBObject> pipeline = new ArrayList<BasicDBObject>();
BasicDBObject projectParams = new BasicDBObject();
projectParams.put("name", 1);
projectParams.put("addresses.state", 1);
projectParams.put("addresses.locs", 1);
projectParams.put("courses", 1);
pipeline.add(new BasicDBObject("$project", projectParams));
pipeline.add(new BasicDBObject("$match", new BasicDBObject("courses.tags", new BasicDBObject("$all", tags))));
pipeline.add(new BasicDBObject("$unwind", "$addresses"));
cmdBody.put("pipeline", pipeline);
if( !getDatastore().getDB().command(cmdBody).ok() ){
throw new MongoException(getDatastore().getDB().command(cmdBody).getErrorMessage());
}
return (BasicDBList) getDatastore().getDB().command(cmdBody).get("result");
}
I have 2 problems with this implementation:
1- This query return all institutions courses if one course match some parameter. For instance, if I search for java and the institution has some Java course, all courses will return
2- Seems like $all doesn't work so well. It looks like my query is searching for some educational institution which has those tags in its courses instead for some course which has those tags inside
Someone can tell me what I am doing wrong?
Upvotes: 0
Views: 1423
Reputation: 3150
You have to unwind the courses first otherway it will be treated like an array and the query will try to find you whole documents(institution) reather than the list elements(courses)
pipeline.add(new BasicDBObject("$project", projectParams));
pipeline.add(new BasicDBObject("$unwind", "$courses"));
pipeline.add(new BasicDBObject("$match", new BasicDBObject("courses.tags", new BasicDBObject("$all", tags))));
pipeline.add(new BasicDBObject("$unwind", "$addresses"));
Upvotes: 1