2011-11-23 60 views
0

我想要什么:

  • 取一些文件
  • 每一个文件,设置字段:
    • 改变它,如果它存在
    • 添加它,如果它不

我做什么:

// fresh data 
print_r(iterator_to_array($collection->find()->limit(2))); 

// query 
$docs = $collection->find()->limit(2); 
// fetch 
foreach ($docs AS $id => $doc) { 
    // update 
    $collection->update(array('_id' => $doc['_id']), array(
    '$set' => array(
     'existing_field' => 'x', 
     'new_field' => 'y', 
    ), 
), array('multiple' => false)); 
} 

// verify 
print_r(iterator_to_array($collection->find()->limit(2))); 

为什么不说做什么?现有字段未更改,新字段未添加。这种情况可能是错误的?

PS。完整的代码(在它们之间具有大量的垃圾的):http://pastebin.com/CNfCVxex
线33 - 37 - 新鲜数据
线63 - 76 - 查询,取&更新
线79 - 80 - 验证

回答

1

不熟悉你在这里使用的驱动程序,但从你的描述中,你可以实现你想要的单个数据库命中,无需获取/循环/更新..

$ set操作符将插入或更新一个字段取决于它是否存在。

db.Collection.update({}, { $set : { "myfield" : "x" } }, false, true) 

上面将设置在集合中的“X”所有文件“MyField的”字段,或者如果它已经存在,将值更改为“X”。那是你想要达到的目标吗?

+0

我正在使用PHP。无法一次全部更新,因为更新不同。我会认为'$ set'会做我想做的,但由于某种原因它不会:没有改变。你的例子也不包括'限制(2)'顺便说一句。 – Rudie

+0

您可以使用$ set设置两个字段。我不认为我真的明白你想要达到什么目的。如果字段'a'存在,并且如果没有设置字段'b',所以文档不会包含'a',你试图设置字段'a'? – Joe

+0

我正在努力做到这一点,但它不会工作。如果我没有使用'$ set'('{“existing_field”:“x”,“new_field”:“y”}'')传递更新对象,整个文档就会被更新(并且被替换,就像规范说的那样。我使用'$ set',什么也没有发生!Pf? – Rudie

0

我怀疑你需要使用new MongoId将字符串$doc['_id']转换回MongoId。请参阅此页面底部的示例:http://www.php.net/manual/en/class.mongoid.php

+0

'$ doc ['_ id'] instanceof MongoId',not一个字符串,我不认为'新的MongoId($ row ['_ id'] - > {'$ id'})'是必要的。(我试过了,没关系。)没有'$ set',文件更新(但被完全替换),因此条件起作用。 – Rudie

+0

开启详细日志记录并查看实际传递给MongoDB的内容。 –

+0

您的更新还似乎有一个额外的数组包裹$ set命令,为什么?这不会使更新文件'{{$ set:{'existing_field':'x','new_field':'y'}}'? –