我有一个php,linux服务器。它有一个名为notes_docs
的文件夹,其中包含超过600,000个txt文件。 notes_docs
的文件夹结构如下 -
- notes_docs
- files_txt
- 20170831
- 1_837837472_abc_file.txt
- 1_579374743_abc2_file.txt
- 1_291838733_uridjdh.txt
- 1_482737439_a8weele.txt
- 1_733839474_dejsde.txt
- 20170830
- 20170829
我必须提供一个快速文本搜索工具,可以在浏览器上显示结果。因此,如果我的用户搜索" new york",那么所有的文件都有" new york"在它们中,应该以数组形式返回。如果用户搜索" foo",所有文件都带有" foo"在它们中应该归还。
我已经使用scandir
和Directory Iterator
尝试了代码,这太慢了。搜索需要一分多钟,即使这样搜索也没有完成。我尝试了ubuntu find
,这又慢了一分钟才能完成。因为文件夹迭代太多,notes_docs
当前大小超过20 GB。
欢迎任何我可以用它来加快速度的解决方案。我可以进行设计更改,将我的PHP代码集成到另一种语言代码中。在极端情况下我也可以进行基础设施更改(就像在内存中使用一样)。
我想知道业内人士是如何做到这一点的?确实有人,Zip Recruiter都提供文件搜索。
请注意我有2GB - 4GB到RAM,所以不能一直加载RAM上的所有文件。
编辑 - 以下所有输入都很棒。对于那些后来的人,我们最终使用Lucene进行索引和文本搜索。它表现得非常好
答案 0 :(得分:23)
要保持简单:每次要搜索时,都无法快速打开,搜索和关闭600k文档。您的基准测试时间超过一分钟"可能是单个测试帐户。如果您计划通过多用户网站搜索这些内容,您可以快速忘记它,因为您的disk IO
将不在图表中并阻止整个服务器。
所以你唯一的选择是索引所有文件。正如其他所有快速搜索工具一样。无论您是使用评论中提到的Solr还是ElasticSearch,还是构建自己的东西。文件将被编入索引。
考虑到txt
文件是您收到的pdf
个文件的文本版本,我打赌最简单的解决方案是将文本写入数据库而不是文件。无论如何,它不会占用更多的磁盘空间。
然后,您可以在数据库(full text search
,mysql
和其他人支持它)上启用mssql
,并且我确定响应时间会更好。请记住,创建这些indexes
确实需要存储空间,但其他解决方案也是如此。
现在,如果您真的想加快速度,可以尝试在更详细的级别上解析简历。尝试并检索您经常搜索的位置,教育,口语和其他信息,并将它们放在单独的表格/列中。这是一项非常困难的任务,几乎是一个项目,但如果你想要一个有价值的搜索结果,这就是你要走的路。因为在没有上下文的情况下进行文本搜索会产生截然不同的结果,所以只要想想你的例子" new york":
答案 1 :(得分:12)
我不会太深入,但我会尝试提供创建概念验证的指南。
首先从此处下载并提取弹性搜索:https://www.elastic.co/downloads/elasticsearch然后运行它:
bin/elasticsearch
下载https://github.com/dadoonet/fscrawler#download-fscrawler解压缩并运行它:
bin/fscrawler myCustomJob
然后将其停止(Ctrl-C)并编辑相应的myCustomJob/_settings.json
(它已自动创建并且路径已在控制台上打印)。
您可以编辑属性:"url"
(要扫描的路径),
"update_rate"
(你可以1m
),
"includes"
(例如["*.pdf","*.doc","*.txt"]
),"index_content"
(将其设为false,仅保留文件名)。
再次跑:
bin/fscrawler myCustomJob
注意:索引是您以后可能希望使用代码执行的操作,但是现在,它将使用fscrawler
自动完成,它直接与弹性对话。
现在开始将文件添加到您在"url"
属性中指定的目录。
下载适用于Chrome的高级休息客户端并进行以下POST
:
网址:http://localhost:9200/_search
原始有效负载:
{
"query": { "wildcard": {"file.filename":"aFileNameToSearchFor*"} }
}
您将返回匹配文件列表。注意:fscrawler
正在为密钥file.filename
下的文件名建立索引。
现在,您可以使用PHP来执行此查询,而不是使用高级rest客户端。通过REST调用上面的url,或者使用php-client api:https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/_search_operations.html
同样代表索引:https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/_indexing_documents.html
答案 2 :(得分:5)
如果要将所有文件信息保存到数据库中:
<?php
function deep_scandir( $dir, &$query, &$files) {
$count = 0;
if(is_dir($dir)) {
if ($dh = opendir($dir)) {
while (($item = readdir($dh)) !== false) {
if($item != '.' && $item != '..') {
if(is_dir($dir.'/'.$item)){
deep_scandir($dir.'/'.$item, $query, $files);
}else{
$count++;
preg_match("/(\d\_\d+)\_(.*)\.txt/i", $item, $matches);
if(!empty($matches)){
$no = $matches[1];
$str = $matches[2];
$files[$dir][$no] = $str;
$content = addcslashes( htmlspecialchars( file_get_contents($dir.'/'.$item) ), "\\\'\"" );
$query[] = "INSERT INTO `mytable` (id, key, value, path, content)
VALUES\n(NULL, '$no', '$str', '$dir/$item', '$content');";
}
}
}
}
closedir($dh);
}
}
}
echo '<pre>';
$dir = 'notes_docs/files_txt';
$query = [];
$files = [];
deep_scandir($dir, $query, $files);
print_r($files);
echo '<br>';
print_r($query);
现在你可以执行数组中的每一行
foreach($query as $no=>$line){
mysql_query($line) or trigger_error("Couldn't execute query no: '$no' [$line]");
}
输出:
Array
(
[notes_docs/files_txt/20170831] => Array
(
[1_291838733] => uridjdh
[1_482737439] => a8weele
[1_579374743] => abc2_file
[1_733839474] => dejsde
[1_837837472] => abc_file
)
)
Array
(
[0] => INSERT INTO `mytable` (id, key, value, path, content)
VALUES
(NULL, '1_291838733', 'uridjdh', 'notes_docs/files_txt/20170831/1_291838733_uridjdh.txt', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus in nisl quis lectus sagittis ullamcorper at faucibus urna. Suspendisse tristique arcu sit amet ligula cursus pretium vitae eu elit. Nullam sed dolor ornare ex lobortis posuere. Quisque venenatis laoreet diam, in imperdiet arcu fermentum eu. Aenean molestie ligula id sem ultricies aliquet non a velit. Proin suscipit interdum vulputate. Nullam finibus gravida est, et fermentum est cursus eu. Integer sed metus ac urna molestie finibus. Aenean hendrerit ante quis diam ultrices pellentesque. Duis luctus turpis id ipsum dictum accumsan. Curabitur ornare nisi ligula, non pretium nulla venenatis sed. Aenean pharetra odio nec mi aliquam molestie. Fusce a condimentum nisl. Quisque mattis, nulla suscipit condimentum finibus, leo ex eleifend felis, vel efficitur eros turpis nec sem. ');
[1] => INSERT INTO `mytable` (id, key, value, path, content)
VALUES
(NULL, '1_482737439', 'a8weele', 'notes_docs/files_txt/20170831/1_482737439_a8weele.txt', 'Nunc et odio sed odio rhoncus venenatis congue non nulla. Aliquam dictum, felis ac aliquam luctus, purus mi dignissim magna, vitae pharetra risus elit ac mi. Sed sodales dui semper commodo iaculis. Nunc vitae neque ut arcu gravida commodo. Fusce feugiat velit et felis pharetra posuere sit amet sit amet neque. Phasellus iaculis turpis odio, non consequat nunc consectetur a. Praesent ornare nisi non accumsan bibendum. Nunc vel ultricies enim, consectetur fermentum nisl. Sed eu augue ac massa efficitur ullamcorper. Ut hendrerit nisi arcu, a sagittis velit viverra ac. Quisque cursus nunc ac tincidunt sollicitudin. Cras eu rhoncus ante, ac varius velit. Mauris nibh lorem, viverra in porttitor at, interdum vel elit. Aliquam imperdiet lacus eu mi tincidunt volutpat. Vestibulum ut dolor risus. ');
[2] => INSERT INTO `mytable` (id, key, value, path, content)
VALUES
(NULL, '1_579374743', 'abc2_file', 'notes_docs/files_txt/20170831/1_579374743_abc2_file.txt', 'Vivamus aliquet id elit vitae blandit. Proin laoreet ipsum sed tincidunt commodo. Fusce faucibus quam quam, in ornare ex fermentum et. Suspendisse dignissim, tortor at fringilla tempus, nibh lacus pretium metus, vel tempus dolor tellus ac orci. Vestibulum in congue dolor, nec porta elit. Donec pellentesque, neque sed commodo blandit, augue sapien dapibus arcu, sit amet hendrerit felis libero id ante. Praesent vitae elit at eros faucibus volutpat. Integer rutrum augue laoreet ex porta, ut faucibus elit accumsan. Donec in neque sagittis, auctor diam ac, viverra diam. Phasellus vel quam dolor. Nullam nisi tellus, faucibus a finibus et, blandit ac nisl. Vestibulum interdum malesuada sem, nec semper mi placerat quis. Nullam non bibendum sem, vitae elementum metus. Donec non ipsum quis turpis semper lobortis.');
[3] => INSERT INTO `mytable` (id, key, value, path, content)
VALUES
(NULL, '1_733839474', 'dejsde', 'notes_docs/files_txt/20170831/1_733839474_dejsde.txt', 'Nunc faucibus, enim non luctus rutrum, lorem urna finibus turpis, sit amet dictum turpis ipsum pharetra ex. Donec at leo vitae massa consectetur viverra eget vel diam. Sed in neque tempor, vulputate quam sed, ullamcorper nisl. Fusce mollis libero in metus tincidunt interdum. Cras tempus porttitor nunc nec dapibus. Vestibulum condimentum, nisl eget venenatis tincidunt, nunc sem placerat dui, quis luctus nisl erat sed orci. Maecenas maximus finibus magna in facilisis. Maecenas maximus turpis eget dignissim fermentum. ');
[4] => INSERT INTO `mytable` (id, key, value, path, content)
VALUES
(NULL, '1_837837472', 'abc_file', 'notes_docs/files_txt/20170831/1_837837472_abc_file.txt', 'Integer non ex condimentum, aliquet lectus id, accumsan nibh. Quisque aliquet, ante vitae convallis ullamcorper, velit diam tempus diam, et accumsan metus eros at tellus. Sed lacinia mauris sem, scelerisque efficitur mauris aliquam a. Nullam non auctor leo. In mattis mauris eu blandit varius. Phasellus interdum mi nec enim imperdiet tristique. In nec porttitor erat, tempor malesuada ante. Etiam scelerisque ligula et ex maximus, placerat consequat nunc consectetur. Phasellus suscipit ligula sed elit hendrerit laoreet. Suspendisse ex sem, placerat pharetra ligula eu, accumsan rhoncus ex. Sed luctus nisi vitae metus maximus scelerisque. Suspendisse porta nibh eget placerat tempus. Nunc efficitur gravida sagittis. ');
)
答案 3 :(得分:3)
我首先尝试创建一个简单的数据库。主表将具有文件名和文本内容。通过这种方式,您可以利用数据库引擎的查询功能,并且可能会在当前解决方案上实现性能的巨大飞跃。
这将是最简单的解决方案,它可以通过添加将单词与文件名相关联的补充表来增长(这可能是动态完成的,例如在最频繁的搜索中)
答案 4 :(得分:-2)
文件系统或数据库?
为了处理大量数据,您需要使用某种DB。就像谷歌一样!
我应该使用像Mysql这样的关系数据库吗?
在许多情况下(如您的情况),关系数据库和SQL不是正确的选择。
今天,大多数搜索引擎和大数据分析器使用 NOSQL数据库
NOSQL DB比SQL DB快得多。但它们通常使用大量硬件资源(RAM,......)。
您的解决方案