In meinem mongoDB Buchsammlung zurück ich Dokumente wie folgt strukturiert haben:MongoDB Aggregation: Wie nur passende Elemente eines Arrays
/* 0 */
{
"_id" : ObjectId("50485b89b30f1ea69110ff4c"),
"publisher" : {
"$ref" : "boohya",
"$id" : "foo"
},
"displayName" : "Paris Nightlife",
"catalogDescription" : "Some desc goes here",
"languageCode" : "en",
"rating" : 0,
"status" : "LIVE",
"thumbnailId" : ObjectId("50485b89b30f1ea69110ff4b"),
"indexTokens" : ["Nightlife", "Paris"]
}
ich die folgende regex Abfrage führen alle Dokumente zu finden, mit einer indexToken beginnend mit " par“:
{ "indexTokens" : { "$regex" : "^Par" , "$options" : "i"}}
Wenn ich wählen Sie das indexTokens Feld nur wie folgt zurückgegeben werden:
{ "indexTokens" : 1}
Das resultierende DBObject ist
{ "_id" : { "$oid" : "50485b89b30f1ea69110ff4c"} , "indexTokens" : [ "Nightlife" , "Paris"]}
Was würde Ich mag nur zu bekommen, ist das Token/Tag, das die regex abgestimmt (I don0t Sorge um das Dokument zu diesem Zeitpunkt abrufen, weder brauche ich alle Tags des passendes Dokument)
Ist dies ein Fall für das neue Aggregations-Framework unter MongoDB v2.2. ?
Wenn ja, wie kann ich eine Abfrage ändern, so dass das tatsächliche Ergebnis aussehen würde:
{ "indexTokens": [ "Paris", "Paradise Fluss", "Parma", etc ....] }
Bonus Frage (haben Sie die Codez): Wie mache ich es mit dem Java-Treiber?
Vorerst mein Java wie folgt aussieht:
DBObject query = new BasicDBObject("indexTokens", java.util.regex.Pattern.compile("^"+filter+"", Pattern.CASE_INSENSITIVE));
BasicDBObject fields = new BasicDBObject("indexTokens",1);
DBCursor curs = getCollection()
.find(query, fields)
.sort(new BasicDBObject("indexTokens" , 1))
.limit(maxSuggestionCount);
Thx :)
EDIT:
Wie pro Ihre Antworten, die ich meine JAVA-Code wie folgt geändert:
BasicDBObject cmdBody = new BasicDBObject("aggregate", "Book");
ArrayList<BasicDBObject> pipeline = new ArrayList<BasicDBObject>();
BasicDBObject match = new BasicDBObject("$match", new BasicDBObject("indexTokens", java.util.regex.Pattern.compile("^"+titleFilter+"", Pattern.CASE_INSENSITIVE)));
BasicDBObject unwind = new BasicDBObject("$unwind", "$indexTokens");
BasicDBObject match2 = new BasicDBObject("$match", new BasicDBObject("indexTokens", java.util.regex.Pattern.compile("^"+titleFilter+"", Pattern.CASE_INSENSITIVE)));
BasicDBObject groupFilters = new BasicDBObject("_id",null);
groupFilters.append("indexTokens", new BasicDBObject("$push", "$indexTokens"));
BasicDBObject group = new BasicDBObject("$group", groupFilters);
pipeline.add(match);
pipeline.add(unwind);
pipeline.add(match2);
pipeline.add(group);
cmdBody.put("pipeline", pipeline);
CommandResult res = getCollection().getDB().command(cmdBody);
System.out.println(res);
Welche Ausgänge
{ "result" : [ { "_id" : null , "indexTokens" : [ "Paris"]}] , "ok" : 1.0}
Das ist genial!
Vielen Dank!
Sie können dies zu Ihrer ursprünglichen Antwort als eine zweite Lösung hinzufügen. Auf diese Weise werden die Leute nicht verwirrt, warum gibt es zwei Antworten von Ihnen :) – Sammaye
ok. getan, dass .. – cirrus
Dank euch beiden funktioniert es wie ein Charme. Ich habe eine Antwort hinzugefügt, um zu zeigen, wie ich es in JAVA gemacht habe (ich habe nicht den neuesten Treiber, also konnte ich die aggregate() Methode für DBCollection nicht verwenden. – azpublic