У меня есть "_id" и "ProductLot". Как я могу обновить Qty "0" до "1" в массиве Lot, если ProductLot присутствует или добавляет новый элемент Lot, если он отсутствует?
"_id" : ObjectId("5462e44c599e5c6c1300000a"),
"LocationName" : "Putaway",
"Owner" : "",
"Status" : "1",
"Scrap" : "0",
"Lot" : [{
"Qty" :"6",
"ProductLot" : ObjectId("5462dbd9599e5c200e000000"),
"Product" : ObjectId("543ca7be4cf59d400c000004"),
"Movement" :[ {"OriginId" : "266",Qty:2,Type:"DN"},
{"OriginId" : "267" , Qty:1 , Type:"DN"},
{"OriginId" : "2" , Qty:3 , Type:"IM"},
]
},
{
"Qty" :"0",
"ProductLot" : ObjectId("5462dbd9599e5c200e000003"),
"Product" : ObjectId("543ca7be4cf59d400c000004"),
"Movement" :[ {"OriginId" : "266",Qty:2,Type:"DN"},
{"OriginId" : "267" , Qty:1 , Type:"DN"},
{"OriginId" : "2" , Qty:-3 , Type:"IM"},
]
}]
}
EG: У меня есть "ProductLot": ObjectId ("5462dbd9599e5c200e000000"), присутствующий в массиве, поэтому он должен обновлять число от 0 до 1; однако "ProductLot": ObjectId ("5462dbd9599e5c200e00000a") недоступен в массиве, поэтому должен добавить новый элемент в массив.
PHP-код, который не обновляет создание массива добавления каждый раз:
$inventoryId = new \MongoId($_POST["inventoryid"]);
$productLotId = new \MongoId($invlotid);
$originId = $_POST['id'];
//$lotcontent = [ /* whatever this looks like */ ];
$lotcontent = array(
'Qty' => $invqty,
'ProductLot' => new \MongoId($invlotid),
'Product'=>$invproduct,
'Movement'=> array(
array(
'OriginId' => $_POST['id'],
'Qty' => $invqty,
'Type'=> 'DN',
), )
);
$invcolname = 'Inventory';
$result = $mongo->$dbname->$invcolname->update(
// Match an inventory without the specific ProductLot/OriginId element
array(
'_id' => $inventoryId,
'Lot' => array(
'$not' => array(
'$elemMatch' => array(
'ProductLot' => $productLotId,
//'OriginId' => $originId,
),
),
),
),
// Append a new element to the Lot array field
array('$push' => array( 'Lot' => $lotcontent ))
);
$movementcontent = array(
'OriginId' => $_POST['id'],
'Qty' => $invqty,
'Type'=> 'DN',
);
$result = $mongo->$dbname->$invcolname->update(
// Match an inventory without the specific ProductLot/OriginId element
array(
'_id' => $inventoryId,
'Lot' => array(
//'$not' => array(
'$elemMatch' => array(
'ProductLot' => $productLotId,
'Movement'=>array(
'$not' => array(
'$elemMatch' => array(
'OriginId' => $originId,
)
)
)
),
// ),
),
),
// Append a new element to the Lot.Movement array field
array('$push' => array( 'Lot.$.Movement' => $movementcontent ))
);
$result = $mongo->$dbname->$invcolname->update(
// Match an inventory with a specific ProductLot/OriginId element
array(
'_id' => $inventoryId,
'Lot' => array(
'$elemMatch' => array(
'ProductLot' => $productLotId,
//'OriginId' => $originId,
'Movement'=>array(
'$elemMatch' => array(
'OriginId' => $originId,
)
)
),
),
),
// Update the "Qty" field of the first array element matched (if any)
//array( '$set' => array( 'Lot.$.Qty' => 'Updated' )),
array( '$set' => array( 'Lot.$.Movement.$.Qty' => $invqty )),
array('upsert' => true));
Пожалуйста, помогите мне решить это?
Использование $addToSet
в этом случае проблематично, потому что следующие элементы lot
считаются разными:
{
"Qty" :0,
"ProductLot" : ObjectId("5462dbd9599e5c200e000003"),
"Product" : ObjectId("543ca7be4cf59d400c000004"),
"OriginId" : "266"
}
{
"Qty" :5,
"ProductLot" : ObjectId("5462dbd9599e5c200e000003"),
"Product" : ObjectId("543ca7be4cf59d400c000004"),
"OriginId" : "266"
}
Первым элементом, вероятно, будет то, что вы добавляете (с количеством 0 или 1), а второй элемент будет одним и тем же логическим элементом партии, просто с увеличенной величиной. Если последний элемент уже существовал в массиве, я полагаю, вы хотели бы, чтобы ваше приложение увеличивало количество от 5 до 6 вместо добавления первого элемента, который по существу является дубликатом.
Мы определенно нуждаемся в двух обновлениях здесь, но я бы предложил следующее:
// Let assume the following identifiers...
$inventoryId = new MongoId($_POST['inventoryid']);
$productLotId = new MongoId($invlotid);
$originId = new MongoId($_POST['id']);
$lotcontent = [ /* whatever this looks like */ ];
$result = $collection->update(
// Match an inventory without the specific ProductLot/OriginId element
[
'_id' => $inventoryId,
'Lot' => [
'$not' => [
'$elemMatch' => [
'ProductLot' => $productLotId,
'OriginId' => $originId,
],
],
],
],
// Append a new element to the Lot array field
[ '$push' => [ 'Lot' => $lotcontent ] ]
);
MongoCollection::update()
вернет результирующий документ с полем n
указывающим количество затронутых документов. Поскольку мы не используем multiple
параметр и также сопоставляем не более одного документа с помощью _id
, мы можем ожидать, что n
будет либо 0, либо 1. Если n
равно 0, мы либо не смогли найти документ инвентаризации с этим _id
либо мы нашел его, но у него уже был элемент Lot
с идентификаторами продукта и происхождения (т.е. наши критерии $elemMatch
соответствовали чему-то, аннулируя наше отрицание). Если n
равно 1, это значит, что мы нашли документ инвентаризации, он не содержал соответствующий элемент Lot
, и мы добавили его (т.е. наша работа выполнена).
Предполагая, что n
равно 0, мы должны выпустить еще одно обновление и попытаться увеличить количество:
$result = $collection->update(
// Match an inventory with a specific ProductLot/OriginId element
[
'_id' => $inventoryId,
'Lot' => [
'$elemMatch' => [
'ProductLot' => $productLotId,
'OriginId' => $originId,
],
],
],
// Update the "Qty" field of the first array element matched (if any)
[ '$inc' => [ 'Lot.$.Qty' => 1 ] ]
);
Здесь я использую оператор $
positional update для доступа к определенному элементу массива, который был сопоставлен в критериях. Это позволяет нам создавать $inc
не беспокоясь об индексе совпадающего элемента.
Опять же, мы можем проверить $result['n']
здесь. Если он еще 0, то можно предположить, что ни один документ не соответствует нашему _id
(полностью отдельная ошибка). Но если n
равно 1 в этой точке, мы успешно увеличиваем количество и выполняем нашу работу.