【问题标题】:get mongodb _id object after upsert with php使用 php 进行 upsert 后获取 mongodb _id 对象
【发布时间】:2011-05-24 22:57:34
【问题描述】:

查询后是否可以获得新的/更新的_id? 示例代码:

$key = array( 'something' => 'unique' );
$data = array( '$inc' => array( 'someint' => 1 ) );
$mongodb->db->collection->update( $key, $data, array( 'upsert' => true ) );

$key 没有持有新/旧 _id 对象,我认为 $data 也不会,因为它只是一条指令。

【问题讨论】:

    标签: php mongodb upsert


    【解决方案1】:

    是的 -- 可以使用单个查询。

    MongoDB 包含一个findAndModify 命令,该命令可以原子地修改文档并返回它(默认情况下,它实际上是在修改之前返回文档)。

    PHP 驱动程序在集合类中没有为此提供方便的方法(但是——请查看 this bug),但它仍然可以使用(请注意,我的 PHP 很糟糕,所以我很可能有在以下 sn-p) 中出现语法错误:

    $key = array( 'something' => 'unique' );
    $data = array( '$inc' => array( 'someint' => 1 ) );
    $result = $mongodb->db->command( array(
        'findAndModify' => 'collection',
        'query' => $key,
        'update' => $data,
        'new' => true,        # To get back the document after the upsert
        'upsert' => true,
        'fields' => array( '_id' => 1 )   # Only return _id field
    ) );
    $id = $result['value']['_id'];
    

    【讨论】:

    • ahh - findAndModify 我很少使用它,我总是忘记它的存在 :) - 偶尔被证明是错误的 ;)
    • @gnarf:不用担心。让我感到奇怪的是,没有办法在 PHP 中自动获取 _id ——我习惯了 Python 驱动程序,它在每个 upsert 上返回 _id
    【解决方案2】:

    万一有人像我一样偶然发现这个问题,当你调用 MongoCollection->save(); 时,Mongo 实际上会修改输入数组; - 将 id 附加到末尾。 所以,如果你打电话:

    $test = array('test'=>'testing');
    mongocollection->save($test);
    echo $test['_id'];
    

    您将拥有该对象的 mongo id。

    【讨论】:

    • 太棒了。我看不出使用过于复杂的findAndModify 而不是传统的save 没有任何意义,如果它是一个标准,没有多余的装饰,upsert
    • 啊哈!我想知道为什么没有办法在 PHP 中获取 _id 的 upsert ......这应该是公认的答案。
    【解决方案3】:

    我遇到了这个问题,并通过在 upsert 之后查询 _id 来解决它。我想我会添加一些我的发现,以防它们对任何来这里搜索信息的人有用。

    当 upsert 导致在集合中创建一个新文档时,返回的对象包含 _id(这里是一个示例的 print_r):

    Array
    
    (
    
    [updatedExisting] => 0
    
    [upserted] => MongoId Object
        (
            [$id] => 506dc50614c11c6ebdbc39bc
        )
    
    [n] => 1
    [connectionId] => 275
    [fsyncFiles] => 7
    [err] => 
    [ok] => 1
    )
    

    您可以从中获取_id:

    $id = (string)$obj['upserted'];
    

    但是,如果 upsert 导致现有文档被更新,则返回的对象不包含 _id。

    【讨论】:

      【解决方案4】:

      试一试:

      function save($data, $id = null) {
          $mongo_id = new MongoId($id);
          $criteria = array('_id' => $mongo_id);
          // Wrap a '$set' around the passed data array for convenience
          $update = array('$set' => $data);
          $collection->update($criteria, $update, array('upsert' => true));
      }
      

      假设传递的$id 为空,创建一个新的MongoId,否则它只是将现有的$id 转换为一个MongoId 对象。

      希望这会有所帮助:D

      【讨论】:

        【解决方案5】:

        update 方法返回一个数组,其中包含文档 UPSERTED 的 ID:

        Array
        (
            [ok] => 1
            [nModified] => 0
            [n] => 1
            [err] => 
            [errmsg] => 
            [upserted] => MongoId Object
                (
                    [$id] => 5511da18c8318aa1701881dd
                )
            [updatedExisting] => 
        )
        

        【讨论】:

          【解决方案6】:

          您还可以在更新/更新插入中将 fsync 设置为 true,以将 _id 返回到已传递给更新的对象。

          $save = array ('test' => 'work');
          $m->$collection->update(criteria, $save, array('fsync' => true, 'upsert' => true));
          echo $save['_id']; //should have your _id of the obj just updated.
          

          【讨论】:

            猜你喜欢
            • 2012-06-09
            • 2012-10-24
            • 2015-11-09
            • 1970-01-01
            • 2012-01-19
            • 2021-04-15
            • 2018-03-11
            • 2013-06-23
            • 2016-11-18
            相关资源
            最近更新 更多