PHP Mongo Library没有更新一些文档

时间:2016-08-12 11:06:20

标签: php mongodb

我最近开始研究Mongo db。 这是我在数据库 homeconfig 和集合数据

中的mongo db中的示例文档
{
    "_id": {},
    "user_id": "user",
    "rooms": [
           {
            "name": "abhi",
            "metadata": {
                "user_id": "user",
                "is_expired": "false",
                "expired_on": null
            }
        }
    ],
    "sections": [
           {
            "name": "section1",
            "metadata": {
                "user_id": "user",
                "room": "abhi",
                "is_expired": "false",
                "expired_on": null
            }
        }
    ],
    "devices": [
           {
            "id": "aur.01.Jpzp0o",
            "metadata": {
                "section_less": "true",
                "label": "aa",
                "is_active": null,
                "is_loading": null,
                "is_dimmable": null,
                "type": "aura",
                "sub_device": "aur.01",
                "is_favourite": "false",
                "dimming": null,
                "energy_usage": 0,
                "usage_today": 0,
                "avg_usage": 0,
                "ir_control": null,
                "user_id": "user",
                "room": "abhi",
                "section": null,
                "is_expired": "false",
                "expired_on": null
            }
        }
    ]
}

上面显示的JSON只是我文档的一个示例。实际的那个很大,我无法透露原始副本。

以下是我用来更新文档中的集合的功能。

function removeSectionsFromMongo($user_id, $data, $date)
{              
    $collection = (new MongoConnect())->connect('homeconfig', 'data');        
    foreach ($data as $key ) {         
        $update = $collection->updateOne(['user_id'=>$user_id, 'sections' => ['$elemMatch' => ['name' => $key['name'], 'metadata.is_expired' => 'false' ]]],
                ['$set'=>['sections.$.metadata.is_expired'=>'true', 'sections.$.metadata.expired_on'=>$date]]
            );
        if($update->getModifiedCount() == 1)
        {
            echo "Section <".$key['name']."> removed from room <".$key['metadata']['room'].">."."\n";
        }
    }        
}

变量$data是一个如下所示的数组:

Array
(
    [0] => Array
        (
            [name] => Appliances
            [metadata] => Array
                (
                    [user_id] => CubicalPrime
                    [room] => Dhruv
                    [is_expired] => false
                    [expired_on] => 
                )

        )

    [1] => Array
        (
            [name] => Bathroom
            [metadata] => Array
                (
                    [user_id] => CubicalPrime
                    [room] => Dhruv
                    [is_expired] => false
                    [expired_on] => 
                )

        )

    [2] => Array
        (
            [name] => Others
            [metadata] => Array
                (
                    [user_id] => CubicalPrime
                    [room] => Dhruv
                    [is_expired] => false
                    [expired_on] => 
                )

        )

)

当我执行该函数时,它应该更新我传递的数组sections中匹配的文档中的所有$data

但是,它正在更新文件。但是当文档的大小增加时,有时sections中的对象很少没有得到更新。即is_expired字段未更新为true&amp; <{1}}未通过日期更新。

当我再次运行相同的功能时,整个更新将在第二次发生。

仅在查询结果显示修改计数等于1时才回显。这意味着查询正在正确执行。但很少有文档没有得到更新。

expired_on

我试图弄清楚为什么文档第一次没有更新,但第二次更新!!

帮助我解决代码出了什么问题?

2 个答案:

答案 0 :(得分:0)

您可以使用 bulkWrite() API来利用您的更新,就像您在循环中发送异步更新的当前实现一样,这就是为什么您要更新某些文档而某些文档没有更新

bulkWrite() API有一些方法可以允许您的更新操作在服务器上作为批处理执行,因此效率与每次迭代时不发送每个更新操作一样服务器,只有一次在500次操作中说。

以下演示了该方法:

function removeSectionsFromMongo($user_id, $data, $date) {
    $bulkOps = array();      
    foreach ($data as $key ) {  
        $update = [
            'updateOne' => [
                [
                    'user_id' => $user_id, 
                    'sections' => [ 
                        '$elemMatch' => [
                            'name' => $key['name'], 
                            'metadata.is_expired' => 'false' 
                        ]
                    ]
                ], 
                [
                    '$set' => [
                        'sections.$.metadata.is_expired' => 'true', 
                        'sections.$.metadata.expired_on' => $date
                    ]
                ]
            ]
        ];          
        array_push($bulkOps, $update);        
    } 
    $operation = new BulkWrite($databaseName, $collectionName, $bulkOps);
    $result = $operation->execute($primaryServer);
    echo $result->getModifiedCount();
}

答案 1 :(得分:0)

在对我的代码进行了大量挖掘之后,我又添加了一个条件来验证更新记录。

function removeSectionsFromMongo($user_id, $data, $date)
{              
    $collection = (new MongoConnect())->connect('homeconfig', 'data');        
    foreach ($data as $key ) {         
        $update = $collection->updateOne(['user_id'=>$user_id, 'sections' => ['$elemMatch' => ['name' => $key['name'], 'metadata.is_expired' => 'false', 'metadata.room' => $key['metadata']['room'] ]]],
                ['$set'=>['sections.$.metadata.is_expired'=>'true', 'sections.$.metadata.expired_on'=>$date]]
            );
        if($update->getModifiedCount() == 1)
        {
            echo "Section <".$key['name']."> removed from room <".$key['metadata']['room'].">."."\n";
        }
    }        
}

请参阅上面的代码'metadata.room' => $key['metadata']['room']中的内容。

现在记录正在照常更新。此外,我现在正在使用{strong> chridam 建议的bulkWrite()来减少服务器上的负载。见下面的代码:

function removeSectionsFromMongo($user_id, $data, $date, $collection, $debug)
{            
    $bulkOps = array();      
    $sections = array(); $rooms = array(); 
    foreach ($data as $key ) {  
        $update = [
            'updateOne' => [
                [
                    'user_id' => $user_id, 
                    'sections' => [ 
                        '$elemMatch' => [
                            'name' => $key['name'], 
                            'metadata.user_id' => $user_id, 
                            'metadata.room' => $key['metadata']['room'],
                            'metadata.is_expired' => 'false' 
                        ]
                    ]
                ], 
                [
                    '$set' => [
                        'sections.$.metadata.is_expired' => 'true', 
                        'sections.$.metadata.expired_on' => $date
                    ]
                ]
            ]
        ];          
        array_push($bulkOps, $update);
        if($debug)
        {
            array_push($sections, $key['name']);        
            array_push($rooms, $key['metadata']['room']);                 
        }                          
    } 
    $result = $collection->bulkWrite($bulkOps);

    if($result->getModifiedCount() == count($data))
    {
        if($debug)
        {
            for($i = 0; $i < count($sections); $i++)
            {
                echo "Section -".$sections[$i]."- removed from room -".$rooms[$i]."-."."\n";
            }
        }
        return true;
    }
    return false;
}//end removeSectionsFromMongo()

我仍然无法理解为什么我以前的代码没有对记录进行一些验证。 这是Mongo Library中的错误还是别的什么!!

如果有人弄清楚是什么问题,请告诉我。