Подтвердить что ты не робот

"upsert" во встроенном документе

В настоящее время у меня есть следующий набор данных:

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

Если я хочу обновить строку с помощью локали, я бы запускал нечто похожее на:

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

Это работает отлично, пока локаль не существует:

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

поскольку на компоненте_id есть уникальный индекс, это вызовет исключение, которое будет жаловаться на дублирующий ключ.

Есть ли способ автоматически добавить новый "документ" в другую локаль и обновить его, если он уже существует? Согласно документации с использованием оператора позиции не будет работать с "upserting".

4b9b3361

Ответ 1

Вы можете использовать $addToSet, чтобы добавить в набор, убедившись, что нет повторяющегося элемента массива, но это не сработает для вашего "обновления".

Чтобы сделать то, что вы хотите, вам нужно будет изменить структуру данных на что-то вроде:

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

Теперь вы можете сделать обновление в локали nl_NL с помощью только:

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

И новый язык также будет работать, например:

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

Возможно, вы захотите рассмотреть возможность наличия локали как части вложенного объекта, возможно, как в:

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

Это облегчает получение данных в некоторых случаях.