varios texto programa portable para palabras fileseek documentos dentro como buscar archivos archivo abrirlos php linux file-search

php - programa - Búsqueda rápida de texto en más de 600,000 archivos.



fileseek portable (5)

No profundizaré demasiado, pero intentaré proporcionar pautas para crear una prueba de concepto.

1

Primero descargue y extraiga la búsqueda elástica desde aquí: https://www.elastic.co/downloads/elasticsearch y luego ejecútela:

bin/elasticsearch

2

Descargue https://github.com/dadoonet/fscrawler#download-fscrawler extráigalo y ejecútelo:

bin/fscrawler myCustomJob

Luego, deténgalo (Ctrl-C) y edite el myCustomJob/_settings.json correspondiente (se ha creado automáticamente y la ruta se imprimió en la consola).
Puede editar las propiedades: "url" (ruta a escanear), "update_rate" (puede hacer que sea 1m ), "includes" (por ejemplo, ["*.pdf","*.doc","*.txt"] ), "index_content" (haga que sea falso, solo para permanecer en el nombre del archivo).

Corre de nuevo:

bin/fscrawler myCustomJob

Nota: la indexación es algo que luego querrá realizar utilizando el código, pero por ahora, se realizará de forma automática, utilizando fscrawler , que habla directamente con el elástico.

3

Ahora comience a agregar archivos al directorio que especificó en la propiedad "url" .

4

Descargue el cliente de descanso avanzado para Chrome y realice la siguiente POST :

URL: http://localhost:9200/_search

Carga útil en bruto:

{ "query": { "wildcard": {"file.filename":"aFileNameToSearchFor*"} } }

Obtendrá la lista de archivos coincidentes. Nota: fscrawler está indexando los nombres de archivo bajo la clave: file.filename .

5

Ahora, en lugar de usar el cliente de descanso avanzado , puede usar PHP para realizar esta consulta. Ya sea por una llamada REST al url anterior, o utilizando la api de php-client: https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/_search_operations.html

Lo mismo se refiere a la indexación: https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/_indexing_documents.html

Tengo un servidor php, linux. Tiene una carpeta llamada notes_docs que contiene más de 600,000 archivos txt. La estructura de carpetas de notes_docs es la siguiente:

- 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

Tengo que proporcionar una utilidad de búsqueda de texto rápida que pueda mostrar resultados en el navegador. Por lo tanto, si mi usuario busca "Nueva York", todos los archivos que tengan "Nueva York" deberían devolverse en una matriz. Si el usuario busca "foo", se deben devolver todos los archivos con "foo".

Ya probé el código utilizando scandir y Directory Iterator , que es demasiado lento. La búsqueda lleva más de un minuto, incluso cuando la búsqueda no se completó. Intenté find ubuntu, que nuevamente fue lento, tardando más de un minuto en completarse. porque hay demasiadas iteraciones de carpeta y el tamaño actual de notes_docs es superior a 20 GB.

Cualquier solución que pueda usar para hacerla más rápida es bienvenida. Puedo hacer cambios de diseño, integrar mi código PHP para enrollar a otro código de idioma. También puedo hacer cambios en la infraestructura en casos extremos (como al usar algo en la memoria).

¿Quiero saber cómo las personas en la industria hacen esto? La gente de hecho, Zip Recruiter proporciona búsqueda de archivos.

Tenga en cuenta que tengo 2GB - 4GB a RAM, por lo que cargar todos los archivos en RAM todo el tiempo no es aceptable.

EDITAR - Todas las entradas a continuación son excelentes. Para aquellos que vienen más tarde, terminamos usando Lucene para indexación y búsqueda de texto. Se desempeñó muy bien


Para mantenerlo simple: no hay una manera rápida de abrir, buscar y cerrar documentos de 600k cada vez que quiera hacer una búsqueda. Sus puntos de referencia con "más de un minuto" son probablemente con cuentas de prueba únicas. Si planea buscarlos a través de un sitio web multiusuario, puede olvidarlo rápidamente, ya que su disk IO quedará fuera de las listas y bloqueará todo su servidor.

Así que tus únicas opciones son indexar todos los archivos. Al igual que cualquier otra utilidad de búsqueda rápida lo hace. No importa si usa Solr o ElasticSearch como se menciona en los comentarios, o si construye algo propio. Los archivos serán indexados.

Teniendo en cuenta que los archivos txt son versiones de texto de los archivos pdf que recibes, apuesto a que la solución más sencilla es escribir el texto en una base de datos en lugar de en un archivo. No ocupará mucho más espacio en disco de todos modos.

Entonces puede habilitar full text search en su base de datos ( mysql , mssql y otros lo admiten) y estoy seguro de que los tiempos de respuesta serán mucho mejores. Tenga en cuenta que la creación de estos indexes requiere espacio de almacenamiento, pero lo mismo ocurre con otras soluciones.

Ahora, si realmente quiere acelerar las cosas, podría intentar analizar los currículos en un nivel más detallado. Intente y recupere ubicaciones, educación, idiomas hablados y otra información que busque regularmente y colóquelas en tablas / columnas separadas. Esta es una tarea muy difícil y casi un proyecto en sí mismo, pero si desea un resultado de búsqueda valioso, este es el camino a seguir. Debido a que la búsqueda en texto sin contexto da resultados muy diferentes, solo piense en su ejemplo "nueva york":

  1. Yo vivo en Nueva York
  2. Yo estudie en la universidad de nueva york
  3. Me encanta la canción "new york" de Alicia Keys en una biografía personal
  4. Trabajé para New York Pizza
  5. Nací en new yorkshire, Reino Unido
  6. Pasé un verano criando terriers de nueva yorkshire.

Primero intentaría crear una base de datos simple. La tabla principal tendría el nombre del archivo y el contenido del texto. De esta manera, puede aprovechar las funciones de consulta del motor de base de datos y probablemente será un salto sustancial en el rendimiento con respecto a la solución actual.

Esta sería la solución más sencilla y podría crecer agregando tablas complementarias que relacionen palabras con nombres de archivos (esto podría ser algo que se haga dinámicamente, por ejemplo, en las búsquedas más frecuentes)


Si desea guardar toda la información de los archivos en la base de datos:

<?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);

Ahora puedes ejecutar cada linea en array

foreach($query as $no=>$line){ mysql_query($line) or trigger_error("Couldn''t execute query no: ''$no'' [$line]"); }

Salida:

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. ''); )


Sistema de archivos o base de datos?
Para trabajar con una gran cantidad de datos necesitas usar algún tipo de DB. ¡Como lo hace google!

Entonces, ¿debería usar bases de datos relacionales como Mysql?
En muchos casos (como su caso), las bases de datos relacionales y SQL no son la elección correcta. Hoy en día, la mayoría de los motores de búsqueda y analizadores de datos grandes utilizan bases de datos NOSQL .
Los DB de NOSQL son mucho más rápidos que los DB de SQL. Pero usualmente usan muchos recursos de hardware (RAM, ...).

Tu solución

  1. Busca sobre las bases de datos de nosql y comprueba sus diferencias. También debe hacer una búsqueda de texto completo en su base de datos, así que busque la implementación de búsqueda de texto completo en cada uno de ellos. Elige una base de datos NOSQL: Aerospike (la más rápida) - Cassandra - MongoDB - ...
  2. Importe todos los datos de sus archivos en su base de datos.
  3. Elija un lenguaje de programación correcto y rápido (recomiendo no usar PHP).
  4. Diseñe y construya su motor de búsqueda como un servicio.
  5. Conecte su programa principal a su motor de búsqueda.