在我进行mongodb研究的时候,发现PHP客户端有一个很奇怪的现象,对同一个对象进行反复的insert操作是无效的。我们看一下下面的代码:
[codesyntax lang="php"]

<?php
$obj = array('name' => 'jonathan');
$result = $collection->insert($obj);
$obj['language'] = 'chinese';
$result = $collection->insert($obj);

[/codesyntax]

照我一开始自己的理解的话,这样的操作应该会在mongodb里创建两条数据,一条只含有name,而另一条则还包含language。但是事实却不是这么回事,我测试的结果是每次执行这段代码只会插入一条数据,就是只有name那条。这就比较奇怪了,而且我发现这种做法在PHP官方文档里是有说明的,参考MongoCollection::save的文档,你可以在最下面的范例里发现,官方说明里就包含了这个情况。

后来我又读了MongoCollection::batchInsert的文档,这个API最下面的范例给了我一个提示,在insert之后程序把原始对象的_id变量打出来了,本来这个变量应该是不存在的。这个例子我读过后我就明白了,这些API应该都是把传入的array参数作为一个引用传入的,在insert结束后直接修改了传入参数,把_id这个本来不存在的主键变量填充了,所以直接使用那个有主键的参数进行第二次insert当然就失败了。

我写了一段代码来验证我的想法:
[codesyntax lang="php"]

<?php
$obj = array('name' => 'jonathan');
var_dump($obj);
$result = $collection->insert($obj);
var_dump($obj);
$obj['language'] = 'chinese';
$result = $collection->insert($obj);
var_dump($obj);

[/codesyntax]

结果如下:

array(1) {
  ["name"]=>
  string(8) "jonathan"
}
array(2) {
  ["name"]=>
  string(8) "jonathan"
  ["_id"]=>
  object(MongoId)#4 (1) {
    ["$id"]=>
    string(24) "4ed746bd48177eab4c000006"
  }
}
array(3) {
  ["name"]=>
  string(8) "jonathan"
  ["_id"]=>
  object(MongoId)#4 (1) {
    ["$id"]=>
    string(24) "4ed746bd48177eab4c000006"
  }
  ["language"]=>
  string(7) "chinese"
}

这里有3次dump,对象都是同一个参数,你可以发现,在第一次insert之后_id变量 就被填充了。恩,事实就是如此。所以如果想利用上次insert完结的参数进行修改进行2次insert的话,就需要把_id这个变量unset掉,绝对不能用save,否则还是没有insert完成,只是变成update而已。