有没有一种更有效(更快)的方法来搜索和匹配PHP中的JSON文件中的值?

时间:2019-06-17 14:05:56

标签: php arrays json

我有一个API,可以根据订单号搜索信息,如下所示:

file_get_contents('https://www.example.com/api/status.php?os='.$orderId)

status.php具有以下代码:

if (isset($_GET['os'])) { $orderId = strip_tags(htmlspecialchars($_GET['os'])); }

if (isset($orderId)) {

    try {

        $array = \JsonMachine\JsonMachine::fromFile($file);
        // using JSON Machine https://github.com/halaxa/json-machine

        $result = getOrderStatus($orderId, $array);

        if (empty($result)) {

            http_response_code(206);

        } else {

            echo json_encode($result, JSON_UNESCAPED_UNICODE);

        }

    } catch (Exception $e) {

        echo json_encode(array(
            'error' => array(
                'code' => $e->getCode(),
                'message' => $e->getMessage()
            )
        ));

    }

} 

上面的代码加载json文件(当前为1.4MB,大约3000个对象,每个对象15个键/值对),然后将整个解码后的json传递给getOrderStatus函数:

function getOrderStatus($orderId, $array) {

    $resultArray = array();

    foreach ($array as $val) {

        $oid = explode(' ', $val['ORDER TITLE']);
        $oid = $oid[0];
        $oid = explode('_', $oid);
        $oid = $oid[0];

        if ($oid == $orderId) {

            $resultArray['status'] = $val['STAT ID'];

            $resultArray['email'] = $val['STAT CTRL'];

            $resultArray['mzId'] = $val['ORDER ID'];

            $resultArray['mcId'] = $val['COMPANY ID'];

            $resultArray['count'] = $val['NUM PCS'];

        }

    }

    return $resultArray;

}

if($ oid == $ orderId)是否匹配API中的ID是否与键“ ORDER TITLE”的值匹配,在这种情况下,该对象中的其余信息与搜索有关。

这是JSON文件中两个对象的示例:

[
   {
      "INTERNAL ID": "914693",
      "ORDER TITLE": "0108491 A_PRODUCT_NAME",
      "COMPANY ID": "",
      "STAT ID": "1.2",
      "STAT CTRL": "example@example.com",
      "POST ID": "Post",
      "SML": "Transfer",
      "UPDATE": "17.06.2019 10:52:45",
      "TOTAL": "0",
      "NUM PCS": "1",
      "PAID": "",
      "TEXT": "",
      "PROBLEM": ""
   },
   {
      "INTERNAL ID": "914694",
      "ORDER TITLE": "0108494 A_PRODUCT_NAME",
      "COMPANY ID": "",
      "STAT ID": "1.2",
      "STAT CTRL": "example@example.com",
      "POST ID": "Post",
      "SML": "Transfer",
      "UPDATE": "17.06.2019 10:52:45",
      "TOTAL": "0",
      "NUM PCS": "1",
      "PAID": "",
      "TEXT": "",
      "PROBLEM": ""
   }
]

问题是我无法控制JSON文件的格式,因为它是从外部软件导出的。

目前,我正在搜索和匹配大约。 100个订单号。这意味着,使用上面的代码,对于每个订单号-调用API,都需要打开JSON文件,测试了3000个对象中的每个对象是否匹配,并返回了包含信息的数组,所有100次。这就是为什么我认为该过程需要40秒的原因。尽管这是可以接受的,但将来JSON文件中的对象可能多达10倍。

如何使搜索速度更快?我当时想用一个订单号数组调用API,然后一次打开文件并匹配每个订单号。这是正确的方法吗?

1 个答案:

答案 0 :(得分:0)

我最终要做的事情可能太复杂了,但是可以很好地达到目的,并且应该可以适应将来越来越大的json主文件。对于某些背景:Web应用程序用于概述订单和有关订单的详细信息,这意味着需要触摸一些本地和外部API。约在任何给定时间可能有5个人(5个浏览器)正在使用该应用程序。

外部软件通过ftp上传包含大部分信息的大型json文件。

要使整个过程自动化,我发现了incron,它与cron类似,但是它不是按时执行,而是按文件/目录操作(创建,更新,删除,等等。)。当然,这需要对本地服务器的ssh和root访问。

sudo apt install incron

incrontab -e

/route/to/json/file/big.json IN_CLOSE_WRITE /usr/bin/php /route/to/php/load.php

load.php每次更改big.json都会运行。

为了缩短加载时间,我创建了一个基于big.json的带有列的数据库表。 load.php读取big.json并将每个对象保存为数据库表中的一行。现在,通过API提供此信息的代码部分现在从数据库而不是big.json中读取该信息,如注释中所建议。这样将时间从原来的44秒减少到22秒。

尽管将json转换为mysql很有帮助,但我认为各个浏览器都不必继续重复加载过程,因此incron的作用几乎相同,但是一次且仅在文件更改时。

load.php可以过滤不需要的数据,还可以加载所有外部API并将数据与big.json中的数据相关联地合并,然后将所有内容保存到名为data-full.json的新文件中。此结果文件的大小比big.json小16倍。然后,带有datatables.js的浏览器应用程序会在几毫秒内加载此文件。

简而言之:

  • 仅在使用json更新后才加载大型incron文件
  • 将大型json文件转换为mysql
  • 创建一个新的json文件,将过滤后的mysql数据和外部API数据组合在一起
  • Ajax调用json中的“静态”新datatables.js文件
  • 添加新的json文件最近一次在php中用filemtime()更新的时间戳记