En mi colección de libros mongodb tengo documentos estructurados de la siguiente manera:mongodb Agregación: Cómo devolver sólo los elementos coincidentes de una matriz
/* 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"]
}
realizo la siguiente consulta de expresiones regulares para encontrar todos los documentos que tienen de uno indexToken comenzando con " par":
{ "indexTokens" : { "$regex" : "^Par" , "$options" : "i"}}
Si selecciono sólo el campo indexTokens a devolver la siguiente manera:
{ "indexTokens" : 1}
DBOBJECT resultante es
{ "_id" : { "$oid" : "50485b89b30f1ea69110ff4c"} , "indexTokens" : [ "Nightlife" , "Paris"]}
Lo que me gustaría conseguir es sólo el símbolo/tag que coincidía con la expresión regular (I don0t atención sobre cómo recuperar el documento en este punto, no necesito todas las etiquetas de la documento coincidente)
Este es un caso para el nuevo Marco de agregación resuelto bajo MongoDB v2.2. ?
Si es así, ¿cómo puedo modificar mi consulta para que el resultado real se vería así:
{ "indexTokens": [ "París", "Río del Paraíso", "Parma", etc ....] }
Pregunta adicional (¿tiene usted el código?): ¿Cómo lo hago utilizando el controlador Java?
Por ahora mi java parece:
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:
Según sus respuestas he modificado mi código JAVA de la siguiente manera:
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);
Qué salidas
{ "result" : [ { "_id" : null , "indexTokens" : [ "Paris"]}] , "ok" : 1.0}
¡Esto es genio!
¡Muchas gracias!
Puede agregar esto a su respuesta original como una segunda solución. De esta manera, las personas no se confundirán por qué hay dos respuestas tuyas :) – Sammaye
ok. hecho eso ... – cirrus
Gracias a ustedes dos funciona como un encanto. Agregué una respuesta para mostrar cómo lo hice en JAVA (no tengo el controlador más reciente, así que no pude usar el método aggregate() en DBCollection. – azpublic