2012-04-23 16 views
11

Actualmente tengo el siguiente conjunto de datos:'upsert' en un documento incrustado

{ 
    'component_id':1, 
    '_locales':[ 
     { 
      'url': 'dutch', 
      'locale': 'nl_NL' 
     } 
    ] (etc) 
} 

Si quiero actualizar la fila con la configuración regional Me ejecutar algo similar a:

db.components.update(
    {'component_id': 1, '_locales.locale': 'nl_NL'}, 
    {$set: {'_locales.$': {'url': 'new url','locale':'nl_NL'}}, 
    true 
); 

Estos trabajos bien hasta la localidad no existe:

db.components.update(
    {'component_id': 1, '_locales.locale': 'en_US'}, 
    {$set: {'_locales.$': {'url': 'new url','locale':'en_US'}}, 
    true 
); 

ya que hay un índice único en component_id esto va a lanzar una excep quejándose de una clave duplicada.

¿Hay alguna manera de agregar automáticamente el nuevo 'documento' con una configuración regional diferente y actualizarlo si ya existe? De acuerdo con la documentación que usa el operador de posición, no funcionará con 'upserting'.

Respuesta

10

Puede usar $addToSet para agregar a un conjunto y asegurarse de que no haya un elemento de matriz duplicado, pero eso no funcionará para su caso de "actualización".

Con el fin de hacer lo que quiera, tendrá que cambiar su estructura de datos a algo como:

{ 
    "_id" : ObjectId("4f9519d6684c8b1c9e72e367"), 
    "component_id" : 1, 
    "_locales" : { 
     "nl_NL" : { 
      "url" : "dutch" 
     } 
    } 
} 

Ahora usted puede hacer una actualización de la configuración regional nl_NL con sólo:

db.components.update({ component_id: 1 }, { $set: { '_locales.nl_NL.url' : 'new url' } }, true); 

Y un nuevo local funcionará tan bien, como por ejemplo con:

db.components.update({ component_id: 1 }, { $set: { '_locales.en_US.url' : 'American' } }, true); 

Es posible que desee consid er a tener la configuración regional como parte del objeto anidado, así tal vez, como en:

{ 
    "_id" : ObjectId("4f9519d6684c8b1c9e72e367"), 
    "component_id" : 1, 
    "_locales" : { 
     "nl_NL" : { 
      "url" : "dutch" 
      "locale" : "nl_NL"     
     } 
    } 
} 

Esto hace que sea más fácil para recuperar datos en algunos casos.

+1

Hola Derick, gracias por responder. Su sugerencia fue en realidad mi estructura de datos inicial, que cambié a la anterior. Uno de los motivos fue crear los índices en: _locales.url en lugar de en cada configuración regional: _locales.nl_NL.url, _locales.en_US.url etc. Actualmente resuelto esto obteniendo todos los datos _locales y modificando/agregando la configuración regional I estoy trabajando con 'manualmente'. Cuando termine, reemplace las '_locales' actuales con la nueva. Por ahora esto será suficiente, en cuanto al rendimiento, esta podría no ser una muy buena idea. –

+0

Estoy de acuerdo, tener una clave "no definida" no suele ser una buena cosa debido a los índices. A veces, es mejor hacer dos consultas para hacer esa actualización si eso mejora el rendimiento debido a índices/otras razones en otros casos. No hay una verdadera "forma correcta" la mayor parte del tiempo. Juega con él, y si no funciona, cámbialo y ejecuta dos consultas para actualizar. – Derick

+0

@Derick: estoy enfrentando un problema similar. http://stackoverflow.com/questions/32038606/defining-a-map-with-objectid-key-and-array-of-strings-as-value-in-mongoose-schem –

Cuestiones relacionadas