繁体   English   中英

MongoDB:在数组中插入和更新

[英]MongoDB : Insert and Update in an array

我有“ _id”和“ ProductLot”。 如果存在ProductLot,如何将批次数组中的数量“ 0”更新为“ 1”;如果不存在,则如何追加新的批次元素?

"_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's 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条件匹配某项,使我们的$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 ] ]
);

在这里,我使用$位置更新运算符访问条件中匹配的特定数组元素。 这使我们可以编写$inc而不用担心匹配元素的索引。

同样,我们可以在此处检查$result['n'] 如果仍然为0,则可以假定没有文档与_id相匹配(完全独立的错误)。 但是,如果此时n为1,我们就成功地增加了数量,我们的工作就完成了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM