Обновление вложенного документа с запросом $ или условием в mongodb - PullRequest
1 голос
/ 29 марта 2012

У меня есть документ заказа, который выглядит следующим образом

{ 
    "_id" : ObjectId("4f70ba6dfb59c87f6b07a1ad"), 
    "state" : "CART", "storeId" : "1", "userId" : "johndoe", 
    "orderItems" : [
        {
            "productId" : "169",
            "offerId" : "112233",
            "sku" : "product-sku-1",
            "name" : "Product Awesome A",
            "quantity" : 1,
            "retailPrice" : 495,
            "salePrice" : 395
        },
        {
            "productId" : "170",
            "offerId" : "112234",
            "sku" : "product-sku-2",
            "name" : "Product Awesome B",
            "quantity" : 1,
            "retailPrice" : 595,
            "salePrice" : 495
        }
    ]
}

Проблема: я хочу найти orderItem, у которого есть productId или sku со значением product-sku-1, и установить количество в 2.

Итак, я попробовал следующее

db.order.update(
    { 
      "userId":"johndoe", "state":"CART",
      $or: [ 
             {"orderItems.productId":"product-sku-1"}, 
             {"orderItems.sku":"product-sku-1"}
      ]
    },
    { 
      $set : {"orderItems.$.quantity":2}
    }
)

Это дает мне ошибку

"can't append to array using string field name [$]"

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

db.order.update(
    { 
      "userId":"johndoe", "state":"CART",
      "orderItems.sku":"product-sku-1"
    },
    { 
      $set : {"orderItems.$.quantity":2}
    }
)

Мое приложение получает либо sku, либо productId в качестве поля идентификатора. Я не знаю, является ли это sku или productId на момент запроса. Итак, мне нужно иметь возможность запрашивать любое из полей в вложенном документе и обновлять количество.

Обратите внимание, что мне нужно, чтобы обновление было сделано атомарно. Я действительно не хочу делать два обновления одно за другим.

Я что-то здесь упускаю? Есть ли другой элегантный способ сделать это?

Ответы [ 2 ]

4 голосов
/ 30 марта 2012

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

db.order.update(
    { 
      "userId":"johndoe", "state":"CART",
      "orderItems" : { 
          $elemMatch : { $or:[{"productId":"product-sku-1"}, {"sku":"product-sku-1"}] }
      }
    },
    { 
      $set : {"orderItems.$.quantity":2}
    }
)
0 голосов
/ 29 марта 2012

Это использование $ не поддерживается.Запрос $ или не устанавливает значение оператора $ positional, поэтому MongoDB считает, что вы ищете поле с именем "$", что запрещено.

Я предлагаю просто выпустить два обновления,фильтрация по productId, другая фильтрация по sku.Только одно из обновлений фактически изменит документ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...