Есть ли способ обновить список с помощью одного запроса?

Я знаю, что этот вопрос уже задавали раньше, но это другой сценарий. Я хотел бы иметь такую ​​​​коллекцию:

{
    "_id" : ObjectId("4c28f62cbf8544c60506f11d"),
    "pk": 1,
    "forums": [{
        "pk": 1,
        "thread_count": 10, 
        "post_count": 20,
    }, {
        "pk": 2,
        "thread_count": 5, 
        "post_count": 24,
    }]
}

Что я хочу сделать, так это добавить элемент «форум», увеличив счетчики или добавив элемент, если он не существует.

Например, сделать что-то вроде этого (надеюсь, это имеет смысл):

db.mycollection.update({
    "pk": 3,
    "forums.pk": 2
}, {
    "$inc": {"forums.$.thread_count": 1},
    "$inc": {"forums.$.post_count": 1},
}, true)

и имеют:

{
    "_id" : ObjectId("4c28f62cbf8544c60506f11d"),
    "pk": 1,
    "forums": [{
        "pk": 1,
        "thread_count": 10, 
        "post_count": 20,
    }, {
        "pk": 2,
        "thread_count": 5, 
        "post_count": 24,
    }]
},
{
    "_id" : ObjectId("4c28f62cbf8544c60506f11e"),
    "pk": 3,
    "forums": [{
        "pk": 2,
        "thread_count": 1, 
        "post_count": 1,
    }]
}

Я уверен, что могу сделать это в три шага:

  1. Обновите всю коллекцию новым элементом
  2. addToУстановить элемент форума в список
  3. увеличивать счетчики элементов форума с помощью позиционного оператора

Это сказать:

db.mycollection.update({pk:3}, {pk:3}, true)
db.mycollection.update({pk:3}, {$addToSet: {forums: {pk:2}}})
db.mycollection.update({pk:3, 'forums.pk': 2}, {$inc: {'forums.$.thread_counter': 1, {'forums.$.post_counter': 1}})

Вы знаете более эффективный способ сделать это? ТИА, Германо


person Germano    schedule 12.08.2010    source источник


Ответы (1)


Как вы могли заметить, позиционный оператор нельзя использовать в upserts:

Позиционный оператор нельзя сочетать с upsert, так как для него требуется соответствующий элемент массива. Если ваше обновление приводит к вставке, то в качестве имени поля буквально будет использоваться «$».

Таким образом, вы не сможете достичь желаемого результата в одном запросе.

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

// optionally create the document, including the array
db.mycollection.update({pk:3}, {$addToSet: {forums: {pk:2}}}, true)

// update the counters in the array item
db.mycollection.update({pk:3, 'forums.pk': 2}, {$inc: {'forums.$.thread_counter': 1, 'forums.$.post_counter': 1}})
person Niels van der Rest    schedule 03.11.2010
comment
Да, я понял это. Спасибо, в любом случае. - person Germano; 05.11.2010