[英]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.