我正在使用PHP PECL扩展试验MongoDB,但是我很难获得某个更新查询.我在SO上寻找答案,但运气不佳.
我创建了一个基本的集合:
$m = new Mongo;
$collection = $m->testdb->testcollection;
$collection->insert(array(
0, 1, 1, 2, 3, 5
));
Run Code Online (Sandbox Code Playgroud)
使用findOne和var_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
Run Code Online (Sandbox Code Playgroud)
当我想要使用更新时,问题就来了$set.我的查询基于PHP手册中SQL到Mongo Cheat Sheet的底部显示的映射
在这里,我想更新字段0到值100
$obj = $collection->findOne();
$collection->update(
array('_id' => $obj['_id']),
array('$set' => array(0 => 100))
);
Run Code Online (Sandbox Code Playgroud)
重新获取记录显示它保持不变.
我确实想知道我是否做错了_id,但是下面的更新查询确实有效,虽然用新值替换整个记录,而不是简单地更新一个字段.
$collection->update(
array('_id' => $obj['_id']),
array(0 => 100)
);
Run Code Online (Sandbox Code Playgroud)
对象转储:
array
'_id' =>
object(MongoId)[7]
public '$id' => string '4f3bde65a1f7a0315b000000' (length=24)
0 => int 100
Run Code Online (Sandbox Code Playgroud)
有人可以指出我做错了什么,以及如何正确使用$set.我确定它很明显,我只需要第二双眼睛.
非常感谢.
Der*_*ick 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);
?>
进行各种测试的基础上,从注释后yi_H从和答案nnythm我发现以下.
在所有情况下,我使用这个通用代码:
$collection->update(
array('_id' => $obj['_id']),
array('$set' => $updateObj)
);
Run Code Online (Sandbox Code Playgroud)
以下内容根本不起作用:
$updateObj = array(0 => 100);$updateObj = array('0' => 100);这些工作:
$updateObj = array(1 => 100);$updateObj = array('1' => 100);经过一些谷歌搜索和阅读一些Mongo PHP文档后,我发现我可以使用对象而不是数组.所以我尝试了这个:
$updateObj = new stdClass;
$updateObj->{0} = 100;
Run Code Online (Sandbox Code Playgroud)
但我一直无法找出原因......
编辑:
通过mongo扩展源代码
该MongoCollection->update方法执行以下操作,buf已经是指针,newobj是zval(查询的第二个参数).HASH_P只需返回zval的右侧属性进行编码,具体取决于它是数组还是对象.
zval_to_bson(buf, HASH_P(newobj), NO_PREP TSRMLS_CC)
Run Code Online (Sandbox Code Playgroud)
该bson_encode功能执行以下操作,功能相同.buf指针和zval z.
zval_to_bson(&buf, HASH_P(z), 0 TSRMLS_CC);
Run Code Online (Sandbox Code Playgroud)
所以我进行了以下测试.
$updateObj = new stdClass;
$updateObj->{0} = 100;
$one = bson_encode($updateObj);
$updateObj = array(0 => 100);
$two = bson_encode($updateObj);
var_dump($one === $two);
Run Code Online (Sandbox Code Playgroud)
输出是 true
仍然0不知道为什么不在数组中的字段名称工作.
编辑2:
进一步的实验表明,当0更新中包含名称为的字段(仅限数组,对象很好)时,不会对任何字段执行更新
例:
$updateObj = array(
'1' => 200
);
Run Code Online (Sandbox Code Playgroud)
工作,字段1更新.
$updateObj = array(
'0' => 100,
'1' => 200
);
Run Code Online (Sandbox Code Playgroud)
难道没有工作,没有现场0或1更新.
我想我要提交一份错误报告.
| 归档时间: |
|
| 查看次数: |
15626 次 |
| 最近记录: |