2012-06-13 9 views
6

que tengo una colección suceso que voy a través de encontrar una categoría para el evento específico y entonces estoy actualizando mi otra colección usando un empuje $ declaración. El problema es que cuando dos eventos tienen la misma categoría crearán un duplicado, que no quiero.Empuje un elemento de una matriz si no está presente (sin duplicados)

que sé de upserts pero no estoy seguro si son el mejor camino a seguir con respecto a esto? Y estoy un poco confundido cuando se trata de cómo escribir un upsert que funcione con la declaración "$ push".

Así es como mi actualización se ve ahora:

self.users.update({"user_id": event['userid']}, {'$push': {'campaigns': UserCampaign}}) 

..where:

UserCampaign = { 
     "id": campaign['id'], 
     "name": campaign['name'] 
} 

El "UserCampaign" se llena con la misma información de vez en cuando, y ya que mi la colección probablemente sea muy grande. Quiero completar esto de la manera más eficiente posible.

TLDR; Quiero actualizar la matriz en el documento encontrado usando un "push" sin tener el riesgo de obtener duplicados.

Respuesta

11

encontrado una mejor respuesta a mi problema:

Mediante el uso de $ addToSet que no crear duplicados (También se aseguró sin duplicados, donde hicieron antes mediante la adición de todos los diccionarios a una lista):

self.users.update({"user_id": event['userid']}, {'$addToSet': {'campaigns': UserCampaigns[i]}}) 

Si hubiera usado $ push siempre crearía elementos duplicados en 'campañas' dentro de la colección de usuarios. Esto sucedió con y sin upsert.

Por alguna razón $ cada uno no funcionaba, pero no se requería, supongo PyMongo se encarga de eso para mí.

+1

ah, he apuntado varios otros al operador $ addToSet antes, pero creo que la forma en que se formuló la pregunta jugó en las respuestas que se relacionan con las respuestas en lugar de agregar a una matriz de elementos, especialmente cuando su última pregunta resumen explícitamente dice: "actualice mi colección usando un" push "" cuando quiere decir algo como: actualice la matriz en el documento usando un push sin tener elementos duplicados. Edité la pregunta para reflejar mejor sus necesidades reales –

+1

Sí, entiendo que podría ser difícil para ustedes saber lo que necesito. Fue mi pobre explicación del problema la culpable. Lo siento, pero encontré una solución de trabajo y por qué específicamente señalé $ push en el título porque realmente pensaba que era lo que terminaría usando. De todos modos, leí sobre $ addToSet y al instante supe que era el operador el que resolvería mi problema. Gracias por su ayuda y actualicé este hilo para que las personas tan confundidas como yo en el futuro pudieran corregirse, como yo lo hice. – Ms01

9

Envíe a través del tercer argumento en su actualización como verdadero según el MongoDB Docs y PyMongo Docs.

self.users.update({"user_id": event['userid']}, {'$push': {'campaigns': UserCampaign}}, True) 
+0

no puedo encontrarla en la documentación, ¿dónde puedo encontrarlo? Gracias por tu respuesta por cierto! – Ms01

+0

En los documentos que he vinculado, simplemente desplácese hacia abajo a la sección 'upserts'. No pude unirme directamente a él ya que usan llaves en la parte de URI flotante que hace que no muestre el enlace correctamente. –

+0

Agregué el enlace a PyMongo Docs en 'updates()'. El tercer argumento para la función es el indicador 'upsert'. –

1

Christian tiene los argumentos correctos en su respuesta, por lo que voy a dejar esa parte solo (votó su respuesta).

Sin embargo, también se preguntan acerca de cómo evitar duplicados, etc.

La clave aquí es asegurarse de que la parte de los criterios de la consulta de actualización es específico para el nivel que desee. Un upsert (o una actualización) solo es tan bueno como los criterios que ingresas en él. Un upsert insertará un documento nuevo si no encuentra uno que coincida con los criterios, y la actualización solo realizará $ push (o la actualización especificada) si se encuentran los criterios ingresados ​​(puede actualizar múltiples si hay más de uno) doc también se encuentra).

En su caso, la parte de los criterios es:

UserCampaign = { 
     "id": campaign['id'], 
     "name": campaign['name'] 
} 

Asegúrese de que esta parte es único y que va a estar bien - si esto puede coincidir con más de un documento, entonces van a tener duplicados.

+0

Gracias por su respuesta, pero UserCampaign en mi ejemplo no puede ser único. Eso es también lo que pensé. Realmente no quiero que cree una nueva fila en la mesa. Pero con suerte nunca será un inserto, así que supongo que estoy bien, pero todavía hay una pequeña posibilidad. Tal vez debería hacer una lógica básica de python antes de actualizar la base de datos con el contenido. – Ms01

+0

Eso podría ser lo mejor: la otra opción sería imponer la exclusividad para esos criterios, pero parece que eso no es algo que desee por otros motivos. Podría intentar agregar el duplicado para evitar la pérdida de datos pero marcarlo como tal (un campo adicional como {dupe: 1}) para que pueda limpiar más tarde –

+0

Disculpe la respuesta tardía. El motivo por el que no deseo aplicar la exclusividad es porque la fila en la que estoy insertando se recopila antes de insertar estos datos. Puede verlo como una colección de usuarios y luego agregar algunas acciones de usuario. – Ms01

Cuestiones relacionadas