2010-11-28 12 views
7

Basado en una gran respuesta a mi previous question, he resuelto parcialmente un problema que tengo con CouchDB.Vistas de CouchDB: eliminar duplicados * y * ordenar por tiempo

Esto dio como resultado a new view.

Ahora, lo siguiente que tengo que hacer es eliminar los duplicados de esta vista mientras ordenar por fecha.

Por ejemplo, aquí es cómo puede ser que consultar ese punto de vista:

GET http://scoates-test.couchone.com/follow/_design/asset/_view/by_userid_following?endkey=[%22c988a29740241c7d20fc7974be05ec54%22]&startkey=[%22c988a29740241c7d20fc7974be05ec54%22,{}]&descending=true&limit=3 

Resultando en esto:

HTTP 200 http://scoates-test.couchone.com/follow/_design/asset/_view/by_userid_following 
http://scoates-test.couchone.com > $_.json.rows 
[ { id: 'c988a29740241c7d20fc7974be067295' 
    , key: 
    [ 'c988a29740241c7d20fc7974be05ec54' 
    , '2010-11-26T17:00:00.000Z' 
    , 'clementine' 
    ] 
    , value: 
    { _id: 'c988a29740241c7d20fc7974be062ee8' 
    , owner: 'c988a29740241c7d20fc7974be05f67d' 
    } 
    } 
, { id: 'c988a29740241c7d20fc7974be068278' 
    , key: 
[ 'c988a29740241c7d20fc7974be05ec54' 
    , '2010-11-26T15:00:00.000Z' 
    , 'durian' 
    ] 
    , value: 
    { _id: 'c988a29740241c7d20fc7974be065115' 
    , owner: 'c988a29740241c7d20fc7974be060bb4' 
    } 
    } 
, { id: 'c988a29740241c7d20fc7974be068026' 
    , key: 
    [ 'c988a29740241c7d20fc7974be05ec54' 
    , '2010-11-26T14:00:00.000Z' 
    , 'clementine' 
    ] 
    , value: 
    { _id: 'c988a29740241c7d20fc7974be063b6d' 
    , owner: 'c988a29740241c7d20fc7974be05ff71' 
    } 
    } 
] 

Como se puede ver, "clementina" muestra hasta dos veces.

Si cambio la vista para emitir el nombre de fruta/activo como la segunda clave (en lugar de la hora), puedo cambiar la profundidad de agrupación para contraerlas, pero eso no resuelve mi requisito de orden por tiempo . Del mismo modo, con la configuración anterior, puedo ordenar por tiempo, pero no puedo colapsar nombres de activos duplicados en filas individuales (para permitir, por ejemplo, 10 activos por página).

Lamentablemente, esta no es una pregunta fácil de explicar. Tal vez this chat transcript ayudará un poco.

Por favor ayuda. Me temo que lo que necesito hacer todavía no es posible.

S

Respuesta

7

Puede hacerlo utilizando la función de lista. Aquí hay un ejemplo para generar una lista realmente simple que contiene todos los campos de propietario sin engaños. Puede modificarlo fácilmente para producir json o xml o cualquier cosa que desee.

ponerlo en su diseño doc activos dentro de las lists.nodupes y utilizar así: http://admin:[email protected]:5984/follow/_design/assets/_list/nodupes/by_userid_following_reduce?group=true

function(head, req) { 
    start({ 
      "headers": { 
      "Content-Type": "text/html" 
      } 
     }); 
    var row; 
    var dupes = []; 
    while(row = getRow()) { 
    if (dupes.indexOf(row.key[2]) == -1) { 
     dupes.push(row.key[2]); 
     send(row.value[0].owner+"<br>"); 
    } 
    } 
} 
+0

Hola. Probé tu reducción, y no creo que resolvió mi problema: http: // scoates-test.couchone.com/_utils/database.html?follow/_design/asset/_view/by_userid_following_reduce (a pesar de tener la reducción, todavía obtengo "banana" dos veces para "c988a29740241c7d20fc7974be060bb4"). ¿Lo implementé incorrectamente? – scoates

+0

Lo siento, mi primer ejemplo es incorrecto. Funciona solo para valores duplicados. Para las claves necesita usar listas. Cambié el ejemplo. Espero que resuelva tu problema. – Nek

+0

Oh wow. No tenía idea de que estas funciones de lista siquiera existieran. Lo probaré y volveré y acepto si cumple mis necesidades (pero a esta altura ya se ve). ¡Gracias! – scoates

2

Realizar un pedido por un campo y uniquing en otro no es algo que el mapa básico de reducir pueden hacer. Todo lo que puede hacer es ordenar sus datos y aplicar reducir acumulaciones a rangos de claves dinámicas.

Para encontrar la última entrada para cada tipo de fruta, debe consultar una vez por fruta.

Hay algunas maneras de hacer esto que son un poco cuerdo.

Usted querrá una vista con teclas como [fruit_type, fecha], y luego se puede consultar la siguiente manera:

for fruit in fruits 
    GET /db/_design/foo/_view/bar?startkey=["apples"]&limit=1&descending=true 

Esto le dará la última entrada para cada fruta.

La operación de lista se podría usar para hacer esto, simplemente repetiría la primera fila del bloque de cada fruta. Esto sería lo suficientemente eficiente siempre que cada fruta tenga un pequeño número de entradas. Una vez que hay muchas entradas por fruta, estará descartando más datos de los que hace eco, por lo que el enfoque de consultas múltiples en realidad se escala mejor que el enfoque de lista, cuando se llega a un gran conjunto de datos. Afortunadamente, ambos pueden trabajar en el mismo índice de vista, por lo que cuando tengas que cambiarlo no será un gran problema.

+0

El problema que tengo al hacerlo en dos consultas es que no puedo paginar razonablemente los resultados, lo que tengo que hacer . Digamos que necesito las 3 entradas más recientes, y la mayoría son 4: manzana, plátano, plátano, clementina, y si limito a 3, obtendría manzana, plátano, plátano y tendría que descartar el segundo plátano, dejando solo 2 resultados Tal vez simplemente no estoy entendiendo. Trabajando con la idea de la lista de Nek ahora, y parece que podría resolver mi problema, a pesar de no escalar bien si mucha gente tiene el mismo activo (fruta). Gracias por tomarse el tiempo para responder. – scoates

Cuestiones relacionadas