2010-07-22 18 views
29

Estoy tratando de usar CouchDB para una nueva aplicación, y necesito crear una vista que clasifique por varios campos y también filtros por múltiples campos. Aquí hay un documento de ejemplo, he dejado el _id y _rev para ahorrarme algo de tipeo.Clasificación y filtrado de CouchDB en la misma vista

{ 
    "title": "My Document", 
    "date": 1279816057, 
    "ranking": 5, 
    "category": "fun", 
    "tags": [ 
     "couchdb", 
     "technology" 
    ], 
} 

De la documentación, he aprendido que puedo crear fácilmente una vista que ordena por un campo como el ranking.

function(doc) { 
    emit(doc.ranking, doc); 
} 

También he aprendido que puedo filtrar fácilmente por campos, como categoría de

function(doc) { 
    emit(doc.category, doc); 
} 

http://127.0.0.1:5984/database/_design/filter/_view/filter?key=%22fun%22 

mi problema es que tengo que hacer un montón de estas cosas, todo al mismo tiempo. Quiero filtrar según la categoría y también la etiqueta. Debería poder filtrar solo a documentos con categoría de "diversión" y etiqueta de "couchdb". Quiero ordenar los resultados filtrados clasificándolos en orden descendente, luego por fecha en orden ascendente y luego por título en orden alfabético.

¿Cómo puedo crear una vista que combine toda esa clasificación y filtrado combinados?

Respuesta

45

Para emitir más de una información en una tecla, querrá leer en Complex Keys. Lo más probable es que termine en emit() 'una clave que es una matriz compuesta por la categoría y la etiqueta. Por ejemplo ...

function(doc) { 
    for(var i = 0; i < doc.tags.length; i++) 
    emit([doc.category, doc.tags[i]], doc); 
} 

Ahora cuando se consulta ?key=["fun", "couchdb"] obtendrá todos los elementos de la categoría de la diversión etiquetados con "couchdb". O si desea todos los elementos de la categoría divertida, independientemente de su etiqueta, puede consultar con un rango: ?startkey=["fun"]&endkey=["fun", {}]. Solo recuerde, si su artículo tiene varias etiquetas, lo obtendrá varias veces en los resultados (porque emit() hizo el documento una vez por etiqueta).

Para ir al paso adicional de ordenar por calificación, fecha y título, agregará dos elementos más a su matriz: un número entero y la clasificación, fecha o título. Recuerde, puede emit() más de una vez por función de mapa. Un ejemplo de función mapa ...

function(doc) { 
    for(var i = 0; i < doc.tags.length; i++) 
    { 
    emit([doc.category, doc.tags[i], 0, doc.ranking], doc); 
    emit([doc.category, doc.tags[i], 1, doc.title], doc); 
    emit([doc.category, doc.tags[i], 2, doc.date], doc); 
    } 
} 

Ahora su estructura clave es: ["category", "tag", 0 ... 2, rank/title/date]

Básicamente, se está agrupando todas las clasificaciones por debajo de 0, 1 bajo títulos, y las fechas en el punto 2. Por supuesto, está transmitiendo una gran cantidad de datos, por lo que podría dividir cada una de estas agrupaciones en una vista separada en su documento de diseño, o solo devolver el _id del documento como el valor (emit([ ...], doc._id);).

Obtener todo en la categoría de "diversión" con el "couchdb" etiqueta (ascendente):

?startkey=["fun", "couchdb"]&endkey=["fun", "couchdb", {}, {}] 

conseguir todo en la categoría de "diversión" con la etiqueta "couchdb" (descendente):

?startkey=["fun", "couchdb", {}, {}]&endkey=["fun", "couchdb"]&descending=true 

obtener sólo el ranking en la categoría de diversión con la etiqueta couchdb (ascendente):

?startkey=["fun", "couchdb", 0]&endkey=["fun", "couchdb", 0, {}]

obtener sólo el ranking en la categoría de "diversión" con la etiqueta "couchdb" (descendente):

?startkey=["fun", "couchdb", 0, {}]&endkey=["fun", "couchdb", 0]&descending=true 

espero que esto ayude. Las claves complejas comienzan a mostrar realmente qué tan poderoso es Map/Reduce para cortar y cortar los datos.

Saludos.

+0

Gracias esto es realmente útil, pero solo necesito un poco más de ayuda. Ya que está emitiendo los mismos documentos una y otra vez, ¿cómo puedo obtener solo cada documento una vez? – Apreche

+1

No puede, a menos que divida cada una de estas agrupaciones en su propia vista. Por ejemplo,/_design/articles/_view/byRanking,/_design/articles/_view/byDate, etc. Si desea mantener todo en esta vista, deberá gestionar los datos en su cliente. O podría seguir lo que estaba diciendo solo devolviendo el valor _id o null del documento, ya que podría hacer una segunda llamada para obtener el documento una vez. –

+0

Oh espera, no importa. Me lo imaginé. Creo que entendiste mal lo que quería. Quiero ordenar por clasificación, fecha y título simultáneamente. En SQL sería "ordenar por clasificación asc, fecha desc, título asc". Puedo hacer esto haciendo solo una emisión y usar la tecla de inicio y la tecla de fin para filtrar, y el orden ya estará hecho. ¡Gracias! – Apreche

Cuestiones relacionadas