Mongodb php如何获取新文档的ID?

35
创建一个文档:
$db->collection->insert($content);
// $newDocID = ???

如何获取新文档的ID?
4个回答

62
根据文档,你传递给insert的数组将会被添加一个_id字段。
$db->collection->insert($content);
$newDocID = $content['_id'];

11
如果在执行另一个操作之前,您需要获取插入后的ID,则可以考虑添加fsync选项: $db->collection->insert($content, 'fsync' => \TRUE); 这将确保“事务”先完成... - ZagNut
1
请注意,此答案适用于旧的遗留mongo驱动程序。如果您正在寻找新驱动程序的答案,请查看此链接:https://dev59.com/2G855IYBdhLWcg3wHweH#37834261 - King Julien

34

在插入之前,您也可以获取_id。只需将_id字段添加到带有新MongoId的文档中即可。

$content['_id'] = new MongoId();
$db->collection->insert($content);

此外,这样做还有很多好处:

  1. 您不需要像ZagNut在以前的回答中发表评论那样使用fsync标志。因此,您无需等待来自数据库的回复。
  2. 您不需要实际将任何内容插入到数据库中即可获得id。因此,您可以准备一些相关对象,然后“插入或不插入”它们 - 有点像Mongo不支持(但?)的事务。
  3. 您实际上可以在应用程序中生成id,而不是在数据库中生成id,因此您可以在插入之前或之后执行任何操作。

缺点:如果在同一时刻从不同的客户端调用此函数,则可能会出现错误E11000重复键错误索引 - Somnath Muluk
据我了解,这基本上是不可能的。每个mongo id都是由时间戳、机器主机名和增量计数器组合而成的。如果所有客户端都有唯一的主机名,这怎么可能发生呢? - alapeno
@alapeno 为什么你会认为你不会在同一主机名上有多个客户端?虽然根据文档,ID 不仅基于主机,还基于进程、时间戳和递增计数器,因此即使主机名相同,时间戳相同,进程和递增计数器部分也应该不同,所以我也想知道你如何获得重复的键错误?PHP 文档指出 ID 将是唯一的,因此如果存在冲突,那就是 PHP 中的一个 bug。 - Josh Ribakoff
@alapeno:我也是这么想的。但是当每分钟有大约10k个连接时,我已经多次(每周1-2次)收到了这个错误。 - Somnath Muluk
@JoshRibakoff 抱歉,我忘记提到进程 ID(或者说它的哈希值)。 - alapeno
@SomnathMuluk 这很奇怪,你的设置中使用了多少个进程/主机? - alapeno

24

对我来说这个方法有效:

$insertResult = $collection->insertOne($object);
$id = $insertResult->getInsertedId();

这救了我的命!! - Pila
如果您是通过Composer获取驱动程序,则使用这个是正确的选择。 - logicbloke
6
注意:getInsertedId方法将返回一个\MongoDB\BSON\ObjectID实例。要获取实际的ID值,请将其转换为字符串:(string)$insertResult->getInsertedId() - Luke

1

1
推荐使用带有upsert和new标志的findAndModify()函数,听起来如果运行Mongo >= 3.x.x版本是可行的,但这是一种过于复杂且不太便携的方式,因为insert()函数已经可以实现简单的插入并获取ID。 - Josh Ribakoff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接