2010-12-05 24 views
8

Tengo una colección lists donde cada documento tiene una matriz de members. Cada elemento de la matriz members es un documento con una propiedad email, una propiedad de creación date y alguna otra meta. Tengo un índice único en members.email para evitar que se ingrese el mismo correo electrónico en la misma lista dos veces, pero me gustaría conservar el valor original date. Lamentablemente, ni $addToSet ni $push parecen hacer esto.

Ejemplo usando $ empuje:

$lists->update(array('_id' => $list['_id'], 'members.email' => array('$ne' => $email)), array('$push' => array('members' => array(
    'email' => $email, 
    'date' => new MongoDate(), 
    // etc. 
)))); 

Y con $ addToSet:

$lists->update(array('_id' => $list['_id']), array('$addToSet' => array('members' => array(
    'email' => $email, 
    'date' => new MongoDate(), 
    // etc. 
)))); 

Ambos ejemplos reemplazar todo el documento incrustado con el nuevo debido a (supongo) el valor único date. ¿Es posible solo $push el documento "miembro" si members.email no existe o tendré que hacer esto en dos comandos?

Alternativamente, ¿sería mejor escalabilidad sabio poner el members en su propia colección con una propiedad similar a parent_list?

Respuesta

1

¿Por qué no tener una colección donde almacena list_id, email, added_date Luego crearía un índice único en 2 claves list_id y correo electrónico. Eso evitaría la inserción de de un registro con el mismo list_id y correo electrónico

No habrá documentos incrustados. Todavía puede usar find() por list_id

0

Sí, es posible. Consulte el operador $ exists en la sección mongoDB advanced queries. Codifique una condición $ exists en una instrucción where para actualizar solo cuando el correo electrónico de los miembros no exista.

+1

estoy casi seguro de $ existe no es la solución que estoy buscando. – Kevin

5

En mi experiencia, la razón por la que no puede "$ push" o "$ addToSet" es porque sus "miembros" de destino son probablemente un objeto incrustado (o convertido a uno después de su creación). Solo puede usar $ push, $ pushAll, $ addToSet en matrices embebidas ...

Desafortunadamente para nosotros los desarrolladores de PHP una consulta de cursor siempre devuelve los datos como matrices, la mejor forma de comprobar si hay algo así como "miembros" es una matriz u objeto, es ejecutar un find() en el shell mongo y buscar los corchetes rizados/cuadrados ("{}" o "[]" en el resultado.

Espero que esto ayude.

0

IIUC, intente utilizar Upsert para actualizar el documento incrustado (si existe) o insertarlo (si no tiene ninguno). Ver this también.

En cuanto a su segunda pregunta con respecto a la escalabilidad, depende realmente de cada caso ... incrustando el documento en el padre requiere actualizaciones más difíciles y una mayor obtención de datos, pero reduce el recuento de consultas de búsqueda.

1

uso $ne en condiction consulta para filtrar los documentos con los miembros del mismo correo electrónico:

$lists->update(array('_id' => $list['_id'], 
        'members.email' => array('$ne' => $email)), 
       array('$addToSet' => array('members' => array(
        'email' => $email, 
        'date' => new MongoDate(), 
         // etc. 
)))); 
Cuestiones relacionadas