mongodb php находит подобъект и удаляет его, $ inc другой подобъект - PullRequest
1 голос
/ 24 декабря 2010

Я пытаюсь удалить подобъект 'яблоки' из моих документов и обновить свойство 'fruitInventory', уменьшив количество яблок.

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

// Document 1 
{
    "1": {
        "apples": 3,
        "fruitInventory": 21,
        "oranges": 12,
        "kiwis": 3,
        "lemons": 3
    },
    "2": {
        "bananas": 4,
        "fruitInventory": 12,
        "oranges": 8,
    },
    "_id": "1"
}

// Document 2
{
    "1": {
        "apples": 5,
        "fruitInventory": 10,
        "oranges": 2,
        "pears": 3
    },
    "2": {
        "bananas": 4,
        "fruitInventory": 6,
        "cherries": 2,
    },
    "_id": "2"
}

Результат должен быть таким:

// Document 1 
{
    "1": {
        "fruitInventory": 18,
        "oranges": 12,
        "kiwis": 3,
        "lemons": "3"
    },
    "2": {
        "bananas": 4,
        "fruitInventory": 12,
        "oranges": 8,
    },
    "_id": "1"
}

// Document 2
{
    "1": {
        "fruitInventory": 5,
        "oranges": "2",
        "pears": "3"
    },
    "2": {
        "bananas": 4,
        "fruitInventory": 6,
        "cherries": 2,
    },
    "_id": "2"
}

Заранее спасибо за вашу помощь.

Ответы [ 3 ]

2 голосов
/ 31 декабря 2010

В языке запросов MongoDB нет способа обновить документ, используя информацию из документа.Другими словами, нет способа увеличить одно свойство на значение из другого свойства.Конкретно: нет способа увеличить fruitInventory на X, где X - это значение свойства apples как атомарной операции.

Я бы реализовал это, избегая гонок,с двумя findAndModify операциями (видимыми здесь в синтаксисе оболочки Mongo):

var fruit = db.fruit.findAndModify({
 query: {locked: {$ne: true}, "1.apples": {$exists: true}},
 update: {$set: {locked: true}}
});

var fruitInventory = fruit["1"]["fruitInventory"];
var apples = fruit["1"]["apples"];

db.fruit.findAndModify({
  query: {"_id": fruit["_id"]},
  update: {
    $set: {"1.fruitInventory": fruitInventory + apples}, 
    $unset: {locked: false, "1.apples": true}
  }
});

Что происходит так: сначала я нахожу документ, который не заблокирован (подробнее об этом позже), и имеет 1.apples имущество.Документ возвращается и обновляется, чтобы получить свойство locked как одну атомарную операцию.Поскольку у документа теперь есть свойство locked, он не будет найден одним и тем же запросом, поэтому этот запрос можно запускать несколько раз параллельно без риска изменения одного и того же документа дважды.

Затем я извлекаю1.fruitInventory и 1.apples, чтобы упростить следующее выражение.

Второй findAndModify обновляет свойство 1.fruitInventory с новой суммой и отменяет свойство 1.apples, а также locked свойство (чтобы вернуть документ в предыдущее, разблокированное состояние).

Чтобы обновить все документы, вам придется многократно запускать этот код, пока первый findAndModify не вернет null (имеется в видунет документов, соответствующих запросу).

1 голос
/ 25 декабря 2010

Используйте $ unset с мульти-обновлением:

> db.whatever.update({}, {$unset : {"1.apples" : true}}, false, true)

В заметке более высокого уровня вы можете использовать более богатые типы данных (например, целые числа обычно следует хранить как целые, есливеская причина, чтобы их не было).

0 голосов
/ 02 января 2011

MongoDB не позволяет модифицировать существующую схему документа. Для этого необходимо удалить документ (или элемент множества). и вставить новый измененный документ (или элемент набора)

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