使用 PHP/Phalcon/MongoDB 在新文档插入期间引用现有的 ObjectId

Reference an existing ObjectId during new document insertion using PHP/Phalcon/MongoDB

我使用以下代码使用 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 次往返中执行它们,我可以在插入 secondaryDoc 时引用 parentDocId

您可以通过使用 Bulk API which is available from MongoDB 2.6 or higher. The current PHP driver should support these methods, where in particular you need the MongoWriteBatch class which extends the MongoInsertBatch class 进行插入操作来利用您的插入操作。本质上,操作可以实现如下:

<?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() 方法添加到一个批处理中,以按提供的顺序发送到服务器以进行串行执行。因此,不是等待服务器对每个插入的写响应,而是分批发送和响应操作,因此往返开销更少。