2009-11-04 11 views
6

Permítanme indicar un ejemplo simple: usted tiene un pedido y un carrito de compras. Una manera en la que preveo persistir esto es guardar un documento de Pedido y un documento de Carro. El documento de pedido podría tener un campo llamado "carrito de compras" cuyo valor es el UUID del documento de carro relevante. Otra forma en que puedo imaginar hacer esto es guardar un documento de pedido con el campo "carrito de la compra" que contiene una matriz asociativa de todo el carro. En otras palabras, en lugar de guardar explícitamente el Carro como un documento independiente, incrusto el documento del Carro en el documento del Pedido.¿Cuál es la forma idiomática de implementar claves externas en CouchDB?

¿Qué pasa si más tarde decidimos que un carrito debería ser persistente, por lo que un usuario recurrente encontrará su carrito a medio terminar esperando por él en todas las sesiones? Imagino que podríamos combinar ambos métodos, manteniendo el carro separado mientras está incompleto e incrustándolo en el documento de pedido cuando se finaliza/compra.

Ambos métodos funcionarían, aunque me preocupa que CouchDB no tenga restricciones de clave externa; en el primer método, el documento del Carro podría eliminarse, dejándolo con un conjunto de datos corrupto.

¿Cómo se decide qué método usar? ¿Es uno de estos métodos más idiomático para CouchDB? ¿Hay algún método que me perdí?

Soy nuevo en CouchDB, así que es difícil para mí ver las ventajas/desventajas de tener una estructura más o menos normalizada.

Respuesta

4

Si, por otro lado, no son uno a uno, entonces utilizando una clave compleja puede usar la intercalación de ver para hacer una combinación.

function(doc) { 
    if (doc.type == 'order') { 
    emit([doc.cartid, 1], doc); 
    } else if (doc.type == 'cart') { 
    emit([doc.id, 0], doc); 
    } 
} 

los documentos serán recopilados por cartid con los pedidos que vienen después del carrito. El código de su aplicación se puede unir fácilmente a esta secuencia y puede realizar consultas mediante una carpeta en particular utilizando la tecla de inicio y la tecla de finalización.

ver: View Collation para las reglas de intercalación.

También puede usar un reductor para unirlos también.

Sólo cambia la función de mapa para esto:

function(doc) { 
    if (doc.type == 'order') { 
    emit([doc.cartid, 1], {cartid: doc.cartid, orders: [doc]}); 
    } else if (doc.type == 'cart') { 
    emit([doc.id, 0], {cartid: doc.id, orders: [], cart: doc); 
    } 
} 

y añadir una función de reducir de esta manera:

function(keys, values) { 
    var out = {cartid: null, orders: [], cart: null}; 
    for (idx in values) { 
    var doc = values[idx]; 
    out['cartid'] = doc.cartid; 
    if (doc.cart) { out['cart'] = doc.cart }; 
    for (idx2 in doc.orders) { 
     out.orders.push(doc.orders[idx2]); 
    } 
    } 
    return out; 
} 

Esto devolverá un solo documento por la compra que será una cartid, una serie de pedir documentos y un documento de carrito.

Disculpa si hay errores en el código anterior, pero no tengo una instancia de prueba de couchdb a mano para probarlos. Sin embargo, debería obtener la idea general y la wiki de CouchDB tiene más detalles.

0

Si los objetos Order y Cart tienen una relación uno a uno (así es como suena), entonces el segundo enfoque tiene más sentido ... simplemente mantenga los objetos asociados contenidos en uno. Eso le da la integridad de datos que está buscando y lo hace simple ;-)

Cuestiones relacionadas