优化跨多个文档的句子搜索

时间:2017-07-06 20:58:02

标签: php search

我在优化使用PHP创建的搜索时遇到问题,此搜索仅供一次使用,因此灵活性并不重要。

我有一系列句子,例如:

$arr = [
   'potato',
   'hi my name is Ivan'
    ..
];

该数组包含大约1k个句子。

我有一个200 GB文件的硬盘。

我需要搜索所有文件并查看文件中是否有任何这些句子,如果是,则以特定格式打印出路径,校验和等。

我面临的问题是搜索时间,在做这样的事情时,效率似乎很低:

$objections = [];
foreach ($files as $file) {

    if (!in_array($file->getExtension(), $allowedExt))
        continue;

    $txt = file_get_contents($file);

    foreach ($words as $word) {
        if (stripos($txt, $word) !== false ||
            stripos($file->getFilename(), $word) !== false
            ) {
            $file->c_md5 = getCMD5($file);
            $objections[] = $file;
        }
    }
}

它自己的搜索时间是1小时+,而我正在购买带有最新i7的新MacBook。随着PHP内存等最大化。

在单词数组中匹配哪个单词无关紧要,所以我想知道是否有更聪明的方法来执行搜索而不是循环文件循环中的单词。 OR的非常长的REGEX字符串会更快吗?

还是有一些第三种方式很快。

3 个答案:

答案 0 :(得分:0)

绝对答案是正则表达式。您应该将其分为三个阶段:

  1. 将您的句子列表转换为一个大的正则表达式或要在循环中运行的正则表达式列表。您可以将空格转换为空格\s,并使搜索变得不贪婪/regex/U

  2. 迭代文件并删除行结尾,用空格替换它。以防万一句子跨越多行。

  3. 使用preg_match查看该句子是否在文件中。如果您决定使用多个正则表达式,则可以在循环中执行此操作。

答案 1 :(得分:0)

正则表达式会为您节省很少或没有。

你可以在点击时突破循环。

Foreach{
    If(hit){
        Break;
    }
}

这将节省搜索其余部分。因此,如果您点击第二次迭代,您将不再需要再执行该文档的998次迭代。

你总是会遇到的问题是打开一个文件,毫无疑问,你的大部分表现都会丢失。

如果这是一项需要多次执行的操作,那么可能值得考虑将所有文件编入索引到专为全文搜索ElasticSearch设计的数据库中。在数据库中,您可以简单地保留对物理文件的引用,以用于下一个操作。 所有这些文件的初始加载和索引无疑将占用大量资源和时间。但是,一旦完成,您的搜索将真的快。

答案 2 :(得分:0)

您可以使用exec

创建一个test.php文件并尝试此代码

  <?php
    exec('grep '.escapeshellarg('end').' '."./test.php",$result);              
    print_r($result);
    /* serach for some sentences
     * keep seraching
     * end of comment */
  ?>

当然,您必须首先测试其性能然后根据您的需要进行定制