douxi8119 2016-08-12 11:06
浏览 44
已采纳

PHP Mongo Library没有更新一些文档

I recently started working on Mongo db. This is my sample document in mongo db in DB homeconfig and collection data

{
    "_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
            }
        }
    ]
}

The JSON shown above is just an example of my documents. The actual one is quite big and I cannot reveal the original copy.

Below is the function I am using to update the sets in the document.

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'].">."."
";
        }
    }        
}

Variable $data is an array shown below:

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] => 
                )

        )

)

When I execute the function, it should update all the sections in my document matching in the array $data passed.

However, It is updating the documents. But when the size of document grows, sometimes few object(s) in the sections not getting update. i.e. the is_expired field is not updating to true & expired_on is not updating withe the date passed.

When I run the same function again, the whole updation takes place in second time.

I'm echoing only when the query result says modified count equal to 1. That means the query is executing properly. But few documents are not getting update.

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

I'm trying to figure out why the document is not getting updated in first time but gets update in second time!!

Help me what's wrong with my code?

  • 写回答

2条回答 默认 最新

  • duanba4942 2016-08-27 07:20
    关注

    After a little big digging into my code, I added one more condition for the validation for updating the records.

    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'].">."."
    ";
            }
        }        
    }
    

    See this in the above code 'metadata.room' => $key['metadata']['room'].

    Now the records are being updated as usual. Also I am now using bulkWrite() as suggested by chridam in other answer for reducing the load on server. See below code:

    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]."-."."
    ";
                }
            }
            return true;
        }
        return false;
    }//end removeSectionsFromMongo()
    

    Still I am not getting why my previous code was not working with a few validation for records. Is it a bug in Mongo Library or something else!!

    If anyone figure out what was the issue, please let me know.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥20 wireshark抓不到vlan
  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上
  • ¥15 c程序不知道为什么得不到结果
  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来