【问题标题】:PHP Mongo Library not updating some the document(s)PHP Mongo 库未更新某些文档
【发布时间】:2016-12-19 09:08:57
【问题描述】:

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

中的 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 字段未更新为 trueexpired_on 未在已过的日期内更新。

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

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

    if($update->getModifiedCount() == 1)
    {
        echo "Section <".$key['name']."> removed from room <".$key['metadata']['room'].">."."\n";
    }

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

帮我看看我的代码有什么问题?

【问题讨论】:

    标签: php mongodb


    【解决方案1】:

    您可以使用 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();
    }
    

    【讨论】:

    • 同样的问题。很少有结果没有得到更新。这些与之前的实现完全相同。 ;-(
    • 看我的回答。我添加了更多的验证参数,代码就像一个魅力一样工作。我还按照您的建议更新了我的代码以使用bulkwrite()
    【解决方案2】:

    在深入研究了我的代码之后,我又添加了一个条件来验证更新记录。

    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' =&gt; $key['metadata']['room'] 中看到这一点。

    现在记录照常更新。此外,我现在正在使用 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 库中的错误还是其他问题!

    如果有人找出问题所在,请告诉我。

    【讨论】:

      猜你喜欢
      • 2021-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-18
      • 2018-06-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多