2012-02-15 74 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);