【问题标题】:Reference an existing ObjectId during new document insertion using PHP/Phalcon/MongoDB在使用 PHP/Phalcon/MongoDB 插入新文档期间引用现有的 ObjectId
【发布时间】:2016-01-20 08:41:55
【问题描述】:

我已使用以下代码使用 robomongo 客户端将主要类别 ID 引用插入到次要类别文档

    var parentDoc = db.getCollection('category').findOne({"slug":"Primary"});
    db.category.insert(
    {
        "name" : "Secondary",
        "slug" : "secondary",
        "taxonomy" : true,

        "ancestors" : [
        {
            "_id" : parentDoc._id,
            "name" : parentDoc.name
        }
        ]
    })

我已经尝试过以下 PHP 风格

$query = '
    {
        "slug" : "fashion"
    }';
    $primaryCategory = Category::findFirst(array(json_decode($query,true))); //phalcon code
    $primary = array();
    $primary['_id'] = $primaryCategory->_id;
    $primary['name'] = $primaryCategory->name;

    $document = array(
            "name" => "Secondary2",
            "slug" => "secondary",
            "taxonomy" => true,
            "ancestors" => array($primary)
    );
    $category = $app->mongo->selectCollection('category');//phalcon style of fetching collection handle
    $category->insert($document);

    });

并尝试了 Phalcon 风格

$query = '
    {
        "slug" : "fashion"
    }';
    $primaryCategory = Category::findFirst(array(json_decode($query,true)));
    $cat = new Category(); // new secondary category
    $cat->name = 'Secondary';
    $cat->slug = 'secondary';
    $cat->taxonomy = true;
    $cat->ancestors = array();
    $primary = array();
    $primary['_id'] = $primaryCategory->_id;
    $primary['name'] = $primaryCategory->name;
    array_push ( $cat->ancestors, $primary );
    $cat->save();

在上面的代码中,服务器和 mongo 之间有 2 次往返

  1. 第一个获取parentDoc
  2. 第二个用于插入带有 parentDoc 引用 Id 的 secondaryDoc

是否可以在 1 次往返中执行它们,我可以在辅助文档插入时引用 parentDocId

【问题讨论】:

    标签: php mongodb phalcon


    【解决方案1】:

    您可以使用 MongoDB 2.6 或更高版本中提供的 Bulk API 来利用您的插入操作。当前的 PHP 驱动程序应该支持这些方法,特别是您需要扩展 MongoInsertBatch 类的 MongoWriteBatch 类以进行插入操作。本质上,该操作可以实现如下:

    <?php
        $mc = new MongoClient("localhost");
        $collection = $mc->selectCollection("test", "category");
    
        $batch = new MongoInsertBatch($collection);
        $counter = 0;
        $query = array("slug" => "Primary");
    
        foreach ($collection->find($query) as $doc ) {
    
            $primary = array();
            $primary['_id'] = $doc->_id;
            $primary['name'] = $doc->name;
    
            $doc = array(
                "name" => "Secondary2",
                "slug" => "secondary",
                "taxonomy" => true,
                "ancestors" => array($primary)
            );
            $batch->add($doc);
            $counter++;
    
            if ( $counter % 1000 === 0 ) {
                $ret = $batch->execute(array("w" => 1));
                $counter++;
                $batch = new MongoInsertBatch($collection);        
            }
        }
    
        if ( $counter > 0 ) {
            $ret = $batch->execute(array("w" => 1));
        }
    ?>
    

    在上面,每个find() 查询和插入操作都通过.add() 方法添加到批处理中,然后按照提供的顺序发送到服务器,以供串行执行。因此,无需等待服务器对每个插入的写入响应,而是分批发送和响应操作,因此往返的开销更少。

    【讨论】:

    • 我认为这是一个很好的答案。就我而言,只有 2 个操作。那么 MongoBatch 操作是否会成为开销,我也很想了解如果第一个操作失败,批处理是否会通过第一个操作?以及批处理操作的返回类型。我们说话的时候我正在研究。您也可以更新您的答案。谢谢
    • 这个answer 最好地解释了背后的概念,但本质上,批量 API 通过在 1000 个条目的批量更新语句中提交所有内容来减轻异步写入调用,从而通过不在单个语句中发送所有内容来执行高效的写入操作,而是分成可管理的“批次”以进行服务器承诺。
    猜你喜欢
    • 2019-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-03
    相关资源
    最近更新 更多