2012-02-15 55 views
12

我正在嘗試使用PHP PECL擴展MongoDB,但我很難讓某個更新查詢工作。我已經在SO上尋找答案,但運氣不佳。

我已經創建了一個基本的集合:

$m = new Mongo; 
$collection = $m->testdb->testcollection; 

$collection->insert(array(
    0, 1, 1, 2, 3, 5 
)); 

使用findOnevar_dump記錄顯示如下:

array 
    '_id' => 
    object(MongoId)[6] 
     public '$id' => string '4f3bde65a1f7a0315b000000' (length=24) 
    0 => int 0 
    1 => int 1 
    2 => int 1 
    3 => int 2 
    4 => int 3 
    5 => int 5 

問題是當我想用$set更新。我立足於PHP手冊朝SQL to Mongo Cheat Sheet底部顯示

在這裏,我想更新場0看重映射我的查詢100

$obj = $collection->findOne(); 

$collection->update(
    array('_id' => $obj['_id']), 
    array('$set' => array(0 => 100)) 
); 

重新取的記錄顯示,它遺體不變的

我做了,我懷疑是否是自己做錯事與_id,但是下面的更新查詢確實工作,儘管有新的值替換整個記錄,而不是簡單地更新一個字段。

$collection->update(
    array('_id' => $obj['_id']), 
    array(0 => 100) 
); 

對象轉儲:

array 
    '_id' => 
    object(MongoId)[7] 
     public '$id' => string '4f3bde65a1f7a0315b000000' (length=24) 
    0 => int 100 

可有人請指出我在做什麼錯誤,以及如何正確使用$set。我確信這很明顯,我只需要再看一眼。

非常感謝。

+0

做這項工作:'陣列( '$設置'=>陣列(1 => 100))'? – 2012-02-15 20:56:51

+0

@yi_H:**有**功能。字段'1'已更新,爲什麼它不適用於字段'0'? – Leigh 2012-02-16 09:12:52

回答

11

我已經做了一些調查,爲什麼會這樣。我不認爲我能找到解決這個問題的方法。

JavaScript有數組和關聯數組/對象之間的差異。 PHP有數組和對象之間的區別。對於PHP,關聯數組是一個數組,對於JavaScript,它是一個對象。

當PHP駕駛員需要的數組轉換成JSON對象時,它試圖找出一個數組是否可以是:正常的陣列,從0開始順序編號的鍵;或關聯數組。當前的實現將任何數組按順序編號的鍵,從0開始的普通數組。而一個正常的數組不包含。這就是問題所在。在驅動程序看到正常數組的情況下,BSON中沒有字段名稱信息發送到服務器,因此服務器無法更新字段。

我不能想辦法來改變這種行爲沒有違反任何形式的現有代碼。所以如果你想使用數字字段名,你必須使用stdClass對象作爲「主文檔」。或者,你可能會推這些鍵爲嵌入文檔,然後更新:

 
<?php 
$m = new Mongo; 
$collection = $m->demo->testcollection; 

$collection->insert(array(
    "_id" => 'bug341', 
    'data' => array(0, 1, 1, 2, 3, 5) 
)); 

$obj = $collection->findOne(); 

$update = array('data.0' => 'zero int'); 

$collection->update(
    array('_id' => 'bug341'), 
    array('$set' => $update) 
); 


$obj = $collection->findOne(); 
var_dump($obj); 
?> 
0

您不能在mongodb中使用數字作爲有效的字段名稱。試着把你的領域「0」放在引號中,這就是它在現實中的實現方式。

+0

'array('$ set'=> array('0'=> 100))'具有相同的結果,字段'0'不被更新。 – Leigh 2012-02-16 09:12:03

+2

PHP數組鍵是字符串... – 2012-02-16 10:45:33

9

nnythmyi_H和答案進行各種測試的基礎上,註釋之後,我發現以下。

在任何情況下,我使用這個共同的代碼:

$collection->update(
    array('_id' => $obj['_id']), 
    array('$set' => $updateObj) 
); 

下不工作的時候:

  • $updateObj = array(0 => 100);
  • $updateObj = array('0' => 100);

這些做的工作:

  • $updateObj = array(1 => 100);
  • $updateObj = array('1' => 100);

有點google搜索和閱讀一些蒙戈PHP文檔中的後,我發現我可以使用對象而不是數組。所以我試過這個:

$updateObj = new stdClass; 
$updateObj->{0} = 100; 

這個作品!

但我一直無法找出原因...

編輯:

通過蒙戈擴展源代碼

MongoCollection->update方法執行下列戳,是BUF已經是一個指針,newobj是一個zval(查詢的第二個參數)。 HASH_P只是返回編碼的zval的正確屬性,具體取決於它是一個數組還是一個對象。

zval_to_bson(buf, HASH_P(newobj), NO_PREP TSRMLS_CC) 

bson_encode函數執行以下功能相同的功能。 buf指針和zval z。

zval_to_bson(&buf, HASH_P(z), 0 TSRMLS_CC); 

所以我進行了以下測試。

$updateObj = new stdClass; 
$updateObj->{0} = 100; 

$one = bson_encode($updateObj); 

$updateObj = array(0 => 100); 

$two = bson_encode($updateObj); 

var_dump($one === $two); 

輸出是true

仍然在爲什麼0沒有在數組中的字段名工作損失。

編輯2:

進一步的實驗表明,當包含在更新的0一個名稱的字段(僅陣列,目的是精)沒有更新是在任何字段進行

實施例:

$updateObj = array(
    '1' => 200 
); 

工程,場1被更新。

$updateObj = array(
    '0' => 100, 
    '1' => 200 
); 

是否工作,既不場01被更新。

我想我會提交錯誤報告。

+0

肯定看起來像一個錯誤 - 如果你提交的那種細節的PHP驅動程序(https://jira.mongodb.org/browse/PHP)你有上面我敢肯定克里斯蒂娜&公司將立即淘汰修復:) – 2012-02-16 10:42:36

+0

@AdamC:呃,他們有自己的問題跟蹤器。我已經提交了PECL包的報告[在PHP的bug](https://bugs.php.net/bug.php?id=61103),我討厭複製這些東西,但他們自己的系統似乎更加活躍。 – Leigh 2012-02-16 10:55:00

+0

是的 - 所有官方支持的驅動程序在MongoDB.org網站上的Jira中都有自己的跟蹤程序。如果你對包錯誤沒有任何牽引力,只需打開一個包並引用包錯誤。哦,並在這裏給出詳細信息,鏈接到這個問題/答案不是一個壞主意:) – 2012-02-16 11:12:15

-1
we can update record in mongo db using php example below:- 

$m = new MongoClient(); 
    echo "Connection to database successfully"; 
    $db = $m->unified; 
     $collection = $db->profile; 

$document = array( 
        "name" => $_REQUEST['name'], 
        "email" => $_REQUEST['email'], 
        "age" => $_REQUEST['age'], 
        "address" => $_REQUEST['address'], 
        "comment"=> $_REQUEST['comment'] 

       ); 

       // print_r($document); die; 
      //echo $_REQUEST['pfid']; 
      $filter=array('_id'=>new MongoID($_REQUEST['pfid'])); 
      $update=array('$set'=>$document); 
    $collection->update($filter, $update);