簡體   English   中英

PHP更新MongoDB文檔子數組的多個元素

[英]PHP updating multiple elements of sub-array of MongoDB document

我有以下文檔結構。 我正在嘗試更新holes 子數組內的特定值:

圓形文件

每個holes Array 元素都是一個對象,代表一個高爾夫球洞的得分,具有各種屬性(字段)。 我試圖提供holeGross每個分數更新holeGross字段的能力。 在我的 PHP 網站上,這是使用 POST 表單,它也推送分數數組和round._id值,如下所示:

Array ( [holeScoreHidden] => Array ( [1] => 7 [2] => 7 [3] => 7 [4] => 8 [5] => 7 [6] => 7 [7] => 7 [8] => 7 [9] => 7 ) [roundId] => 60c642db09080f1b50331b2d [submit] => )

我在 MongoDB 論壇上得到了一些幫助,使用了我在 Compass 中測試過的 MongoDB 原生(即 shell)語法,並且有效:

[{$match: {
  _id: ObjectId('60c916684bd16901f36efb3a')
}}, {$set: {
  holes: {
    $map: {
      input: { $range: [0, { $size: "$holes"}]},
      in: {
        $mergeObjects: [
            { $arrayElemAt: ["$holes", "$$this"] },
            { holeGross: { $arrayElemAt: [[9,8,7,6,5,4,3,2,1], "$$this"] } }
          ]
      }
    }
  }
}}]

以此為基礎,我嘗試轉換為 PHP 等效項,如下所示:

function setRoundScores($roundId, $scoresArray) {
        
    $collection = $client->golf->roundTest;
        
    $match = [ '_id' => new MongoDB\BSON\ObjectID( $roundId ) ];
        
    $set = [
        '$set' => [
            'holes' => [
                '$map' => [
                    'input' => [
                        '$range' => [ 0, [ '$size' => '$holes']],
                        'in' => [
                            '$mergeObjects' => [
                                [ '$arrayElemAt' => [ '$holes', '$$this' ]],
                                [ 'holeGross' => [ '$arrayElemAt' => $scoresArray, '$$this' ]]
                            ]
                        ]
                    ]
                ]
            ]
        ]
    ];
        
    $updateOne = $collection->updateOne($match,$set);
        
    return $updateOne->getUpsertedId();
        
}

但是這個錯誤:

致命錯誤:未捕獲的 MongoDB\\Driver\\Exception\\BulkWriteException:'holes.$map' 中以美元 ($) 為前綴的字段 '$map' 對存儲無效。 在 /var/www/html/vendor/mongodb/mongodb/src/Operation/Update.php:228 堆棧跟蹤:#0 /var/www/html/vendor/mongodb/mongodb/src/Operation/Update.php(228 ): MongoDB\\Driver\\Server->executeBulkWrite('golf.roundTest', Object(MongoDB\\Driver\\BulkWrite), Array) #1 /var/www/html/vendor/mongodb/mongodb/src/Operation/UpdateOne.php (117): MongoDB\\Operation\\Update->execute(Object(MongoDB\\Driver\\Server)) #2 /var/www/html/vendor/mongodb/mongodb/src/Collection.php(1075): MongoDB\\Operation\\ UpdateOne->execute(Object(MongoDB\\Driver\\Server)) #3 /var/www/html/functions.php(803): MongoDB\\Collection->updateOne(Array, Array) #4 /var/www/html/ updateRound.php(19): setRoundScores('60cb07d14bd1690...', Array) #5 {main} 在第 228 行的 /var/www/html/vendor/mongodb/mongodb/src/Operation/Update.php 中拋出

我對等效的語法感到非常困惑,或者即使 PHP 驅動程序中提供了相同的方法?

誰能指出語法問題/錯誤?

最后,我可以簡單地替換整個holes子數組,並將其作為一個整體updateOne()提供給updateOne()調用嗎? 這會發送更多的數據,顯然不是最有效的......

*** 更新 ***

@Joe 在最終答案中提供了很大幫助。 @Joe 提供了一行,涵蓋了問題的原因。

對於后代,我想重新發布我的函數的最終語法,以便其他人能夠遵循:

function setRoundScores($roundId, $scoresArray) {
        
    $client = new MongoDB\Client($_ENV['MDB_CLIENT');

    $collection = $client->golf->round;

    $match = [ '_id' => new MongoDB\BSON\ObjectID( $roundId ) ];
        
    $set = [
        '$set' => [
            'holes' => [
                '$map' => [
                    'input' => [
                        '$range' => [ 0, [ '$size' => '$holes']]
                    ],
                    'in' => [
                        '$mergeObjects' => [
                            [ '$arrayElemAt' => [ '$holes', '$$this' ]],
                            [ 'holeGross' => [ '$toInt' => [ '$arrayElemAt' => [ $scoresArray, '$$this' ]]]]
                        ]
                    ]
                        
                ]
            ]
        ]
    ];
        
    $updateOne = $collection->updateOne($match, [$set]);
        
    return $updateOne->getModifiedCount();
        
}

值得注意的是,在將 $_POST 數組的字段轉換為字符串時,還需要將它們轉換為 Int,因此也需要使用 '$toInt' 方法在 DB 上執行此操作。 許多額外的方括號...

此外,這不是一個upsert所以只返回修改后的計數。

update 部分是 updateOne 的第二個參數,必須是一個數組才能使用聚合運算符。

也許用

$updateOne = $collection->updateOne($match,[$set]);

編輯

第二個arrayElemAt表達式中缺少一對括號:

[ 'holeGross' => [ '$arrayElemAt' => $scoresArray, '$$this' ]]

應該

[ 'holeGross' => [ '$arrayElemAt' => [ $scoresArray, '$$this' ]]]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM