【问题标题】:MongoDB: Use save() to update an existing document in a collectionMongoDB:使用 save() 更新集合中的现有文档
【发布时间】:2011-01-01 12:35:17
【问题描述】:

大家。我爱漫画。现在我也在学习爱 mongo :-)

how to use save() to update an existing document in a collection in MongoDB PHP有解释吗?但我无法将其应用于 PHP 的“现实”:-)

> var mongo = db.things.findOne({name:"mongo"});
> print(tojson(mongo));
{"_id" : "497dab624ee47b3a675d2d9c" , "name" : "mongo"}
> mongo.type = "database";
database
> db.things.save(mongo);
> db.things.findOne({name:"mongo"});
{"_id" : "497dab624ee47b3a675d2d9c" , "name" : "mongo" , "type" : "database"}

这是我的测试代码:

<?php
$a=array('_id'=>'test_a','field1'=>'anything');
$b=array('_id'=>'test_a','field2'=>'anything else');

$m=new Mongo();
$c=$m->db->test;
$c->save($a);
$c->save($b);//overwrites the previous record

/*
//With update() it works fine
$filter=array('_id'=>'test_a');
$update=array('$set'=>array('field2'=>'anything else'));
$c->update($filter,$update);
//$c->save($filter,$update);//Also tried...
*/

$f=$c->find();
echo $f->count()." found \n";
$i=iterator_to_array($f);//mongo cursos iterator
$m->close();//disconnect mongo

print_r($i);
?>

事实上,在 PHP 示例中 save() 覆盖了对象,而在 JS 示例中它更新了它。我希望我能像在 JS 中一样在 PHP 中重现。

提前致谢。

【问题讨论】:

  • mongodb.org/display/DOCS/Updating#Updating-ModifierOperations 中,据说“如果 x 有一个 _id 字段,save() 会执行 upsert(x 是一些 JSON 样式对象,如果存在则 upsert 表示更新;如果缺少则插入)”。跨度>
  • 我不明白问题出在哪里,JS和PHP示例不做同样的事情吗?告诉我们你期待什么。不要指望我们设置环境并运行您的代码只是为了查看输出。
  • 感谢您的回复。如果您运行 php 示例,您将看到 save() 覆盖对象,而在 JS 示例中它会更新它。我希望我能像在 JS 中一样在 PHP 中重现。
  • 嗨@Roger - 无需在标题后附加 [SOLVED],在列表中可以通过图形方式识别具有已接受答案的问题。
  • 好吧,如果你这么想,我很抱歉。据我所知,该网站在 SEO 与 Scarp 的斗争中存在严重问题。在标题的某处加上 SOLVED 一词有助于解决这个问题。

标签: mongodb mongodb-php


【解决方案1】:

这些例子做的不一样...

在 JS 示例中,您声明了对象 mongo

> var mongo = db.things.findOne({name:"mongo"});

然后,您修改了 same 对象以添加 type ...

> mongo.type = "database";

在 PHP 示例中,您声明了两个对象 ...

$a=array('_id'=>'test_a','field1'=>'anything');
$b=array('_id'=>'test_a','field2'=>'anything else');

这就像在 JS shell 中执行以下操作...

> var apples = db.things.findOne({name:"mongo"});
> var orange = db.things.findOne({type:"database"});

所以 apples 是与 oranges 不同的对象/文档 ...因此当您运行 save() 并传递 NEW 对象时完全覆盖旧对象。

您的 update() 工作正常,因为您搜索了对象...

$filter=array('_id'=>'test_a');

然后在那个对象上运行更新;传递新字段而不是传递 新对象 来替换它...

$update=array('$set'=>array('field2'=>'anything else'));
$c->update($filter,$update);

在 JS 示例中,您只有 一个对象,因此它基本上将其附加到更新而不是替换它。

正确的 PHP 代码

以下 PHP 将复制您在 JS shell 中所做的事情...

<?php

$connection = new Mongo();
$db = $connection->foo;
$collection = $db->testing;

// create new object & save
$a = array('color'=>'red');
$collection->save($a);

// add type = fruit to existing object & save
$a['type'] = 'fruit';
$collection->save($a);

// print out results.
echo "<pre>";
var_dump($collection->findOne(array("color" => "red")));
echo "</pre>";

?>

注意:我强烈建议您不要设置自己的对象 _id,而是让驱动程序为你就像我在上面的例子中所做的那样。

【讨论】:

  • 贾斯汀,谢谢你非常精彩的回答。在我的示例中,我认为 save() 仅被提供数组内容,而不是考虑 $a$b 实际上是不同的对象。实际上,在 JS 示例中,“upsert”之前有一个findOne()。这个findOne() 出现在PHP update() 中,正如您所说的那样,在$filter=array('_id'=&gt;'test_a'); 中,因此下一个参数中的任何内容都将插入到该对象中。谢谢你的最后一个例子,它是完美的。
  • 我正在用我唯一的 _id 喂 Mongo,以免重复我自己,因为我需要一种独特的、简单的方法来识别一个值,以便将来进行更新。我很自然地使用_id 字段。但是,如果有充分的理由不这样做,我会很乐意将其放在其他领域,让 Mongo 自己决定。请告诉我为什么不建议使用_id 字段?
  • 太棒了!如果我回答了您的问题,请将其标记为“答案”,以便旁边有一个大的绿色复选标记!
  • 一般你应该使用内置的_id(你也可以单独添加你自己的)。更多信息在这里:mongodb.org/display/DOCS/Object+IDs
  • 其实设置自己的对象_id是完全可以接受的。它在文档中明确说明了这一点:mongodb.org/display/DOCS/Object+IDs。我假设您不建议这样做,因为它会自动确保唯一的 _id。在某些情况下——我无法在评论环境中详细说明——最好手动设置你的 _id,即使只使用默认的 MongoId。不过答案很好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多