2010-07-28 11 views
5

Digamos que tengo dos tipos de documentos almacenados en mi base de datos CouchDB. Primero, con el tipo de propiedad establecido en , póngase en contacto con y el segundo con el teléfono . Tipo de contacto documento tiene otra propiedad llamada nombre. El tipo de teléfono tiene el número de propiedades y el ID de contacto para que pueda hacer referencia a la persona de contacto. Este es un escenario trivial de uno a muchos donde un contacto puede tener N números de teléfono (sé que se pueden insertar en un solo documento de contacto, pero necesito demostrar la relación uno a muchos con documentos diferentes).CouchDB view componiendo objetos JSON con matrices incorporadas de dos documentos separados

ejemplo de datos sin procesar con Scott tiene 2 números de teléfono y Matt tiene de 1 número:

{_id: "fc93f785e6bd8c44f14468828b001109", _rev: "1-fdc8d121351b0f5c6d7e288399c7a5b6", type: "phone", number: "123456", contact_id: "fc93f785e6bd8c44f14468828b00099f"} 
{_id: "fc93f785e6bd8c44f14468828b000f6a", _rev: "1-b2dd90295693dc395019deec7cbf89c7", type: "phone", number: "465789", contact_id: "fc93f785e6bd8c44f14468828b00099f"} 
{_id: "fc93f785e6bd8c44f14468828b00099f", _rev: "1-bd643a6b0e90c997a42d8c04c5c06af6", type: "contact", name: "Scott"} 
{_id: "16309fcd03475b9a2924c61d690018e3", _rev: "1-723b7c999111b116c353a4fdab11ddc0", type: "contact", name: "Matt"} 
{_id: "16309fcd03475b9a2924c61d69000aef", _rev: "3-67193f1bfa8ed21c68e3d35847e9060a", type: "phone", number: "789456", contact_id: "16309fcd03475b9a2924c61d690018e3"} 

función de mapa:

function(keys, values) { 
    var output = {}; 

    for(var elem in values) { 
    if(values[elem].type == "contact") { 
     output = { 
     "ID": values[elem]._id, 
     "Name": values[elem].name, 
     "Type": values[elem].type, 
     "Phones": [] 
     }; 
    } else if (values[elem].type == "phone") { 
     output.Phones.push({ 
     "Number": values[elem].number, 
     "Type": values[elem].type 
     }); 
    } 
    } 

    return output; 
} 

group_level se establece en:

function(doc) { 
    if (doc.type == "contact") { 
    emit([doc._id, 1], doc); 
    } else if (doc.type == "phone") { 
    emit([doc.contact_id, 0], doc); 
    } 
} 

función Reducir 1 debido a las teclas en la función de Mapa. Ahora puedo tener en mis contactos con los teléfonos incluidos, por ejemplo, así:

http://localhost:5984/testdb2/_design/testview/_view/tv1?group_level=1 

O buscar algún contacto con startkey y endkey así:

http://localhost:5984/testdb2/_design/testview/_view/tv1?group_level=1&startkey=[%22fc93f785e6bd8c44f14468828b00099f%22]&endkey=[%22fc93f785e6bd8c44f14468828b00099f%22,{}] 

resultados se ven exactamente como quiero - contactos tendrán teléfonos integrados de acuerdo con la relación de uno a muchos. Y aquí va la pregunta: ¿Es esta la forma correcta de usar las funciones de MapReduce en CouchDB? ¿Hay algún problema de rendimiento notable al usar este enfoque?

Respuesta

7

En general, utiliza menos espacio en disco si no lo hace en emit(...,doc).

Es posible que desee reconsiderar tener una función de reducción en absoluto. Realmente no es necesario obtener los datos que necesita. Por ejemplo, algo similar a lo siguiente puede usar menos espacio en disco y funcionar mejor si tiene una gran cantidad de registros.

Además, creo que está contra la corriente de CouchDB crear más datos en una función de reducción que la que contienen sus documentos. No estás haciendo eso en este caso, pero estás siguiendo un patrón que podría llevarte a problemas más adelante. Se llama reducir por una razón. :-)

Así que algo como esto es más cierto CouchDB:

function(doc) { 
    if (doc.type == "contact") { 
    emit([doc._id, 0], { 
     "Name": doc.name, 
     "Type": doc.type 
    }); 
    } else if (doc.type == "phone") { 
    emit([doc.contact_id, 1], { 
     "Number": doc.number, 
     "Type": doc.type 
    }); 
    } 
}

de consulta para un contacto en particular, así:

http://localhost:5984/testdb2/_design/testview/_view/tv1? 
    startkey=[%22fc93f785e6bd8c44f14468828b00099f%22, 0] 
    &endkey=[%22fc93f785e6bd8c44f14468828b00099f%22,1] 

Por supuesto, usted no obtiene resultados en el mismo Estructura JSON como antes, pero creo que esto se comporta mejor dentro de CouchDB.

0

Esta respuesta es completamente apócrifa y anecdótica, pero así es exactamente como he trabajado con relaciones de uno a muchos en CouchDB. Si hay problemas de escala, todavía no los he visto. (Pero admito que no he intentado demasiado para encontrarlos.)

Aunque, en su función de mapa, ¿por qué tiene su teléfono ordenado para salir primero (0) antes del contacto (1)? Su función de reducción requiere el orden opuesto.

+0

Se ordena de esta manera porque cuando accedo a la vista directamente a través del navegador, debería insertar descending = true en la url. – yojimbo87

Cuestiones relacionadas