Meilleures pratiques pour l’archivage consultable de milliers de documents (pdf et / ou xml)

Revisiter un projet bloqué et rechercher des conseils pour moderniser des milliers de “vieux” documents et les rendre disponibles via le web.

Les documents existent sous différents formats, certains étant obsolètes: ( .doc , PageMaker , copie papier (OCR), PDF , etc.). Des fonds sont disponibles pour migrer les documents dans un format «moderne», et de nombreuses copies papier ont déjà été converties en documents PDF. À l’origine, nous avions supposé que le format PDF serait le format final, mais nous sums ouverts aux suggestions (XML?) .

Une fois que tous les documents sont dans un format commun, nous aimerions rendre leur contenu disponible et consultable via une interface Web . Nous aimerions avoir la possibilité de ne retourner que les parties (pages?) Du document entier où une recherche “hit” est trouvée (je pense que Lucene / elasticsearch rend cela possible?!?). Peut-il être plus flexible si le contenu est tout XML? Si oui, comment / où stocker le XML? Directement dans la firebase database ou en tant que fichiers discrets dans le système de fichiers? Qu’en est-il des images / graphiques intégrés dans les documents?

Curieux de savoir comment les autres pourraient aborder cela. Il n’y a pas de réponse “erronée” Je cherche juste le plus d’intrants possible pour nous aider à continuer.

Merci pour tout conseil.

En résumé: je vais recommander ElasticSearch , mais brisons le problème et expliquons comment le mettre en œuvre:

Il y a quelques parties à cela:

  1. Extraire le texte de vos documents pour les rendre indexables
  2. Rendre ce texte disponible en tant que recherche en texte intégral
  3. Retour des extraits mis en évidence de la doc
  4. Savoir où dans la doc ces extraits sont trouvés pour permettre la pagination
  5. Renvoyer la doc complète

Que peut fournir ElasticSearch:

  1. ElasticSearch (comme Solr) utilise Tika pour extraire du texte et des métadonnées d’une grande variété de formats de doc
  2. De toute évidence, il fournit une puissante recherche de texte intégral. Il peut être configuré pour parsingr chaque document dans la langue appropriée, en améliorant la pertinence de certains champs (par exemple, le titre plus important que le contenu), les ngrammes, etc.
  3. Il peut renvoyer des extraits mis en évidence pour chaque résultat de recherche
  4. Il ne sait pas où ces extraits se produisent dans votre doc
  5. Il peut stocker le document original en tant que pièce jointe ou stocker et renvoyer le texte extrait. Mais ça va retourner tout le document, pas une page.

Vous pouvez simplement envoyer le document entier à ElasticSearch en pièce jointe, et vous obtiendrez une recherche en texte intégral. Mais les points de blocage sont (4) et (5) ci-dessus: savoir où vous vous trouvez dans un document et renvoyer des parties d’un document.

Le stockage de pages individuelles est probablement suffisant pour vos besoins (même si vous pouvez également passer au niveau du paragraphe), mais vous souhaitez les regrouper de manière à ce qu’un document soit renvoyé dans les résultats de recherche, même si les mots-clés de recherche apparaissent. sur différentes pages.

Tout d’abord la partie indexation: stocker vos documents dans ElasticSearch:

  1. Utilisez Tika (ou tout ce qui vous convient) pour extraire le texte de chaque document. Laissez-le en texte brut ou en HTML pour conserver un certain formatage. (oubliez XML, pas besoin)
  2. Extraire également les métadonnées pour chaque document: titre, auteurs, chapitres, langue, dates, etc.
  3. Stockez le document original dans votre système de fichiers et enregistrez le chemin afin de pouvoir le servir ultérieurement
  4. Dans ElasticSearch, indexez un doc “doc” contenant toutes les métadonnées et éventuellement la liste des chapitres
  5. Indexer chaque page comme une “page” doc, qui contient:

    • Un champ parent contenant l’ID du document “doc” (voir ci-dessous “Relation parent-enfant”)
    • Le texte
    • Le numéro de page
    • Peut-être le titre ou le numéro du chapitre
    • Toutes les métadonnées que vous souhaitez rechercher

Maintenant pour la recherche. La manière dont vous procédez dépend de la manière dont vous souhaitez présenter vos résultats – par page ou regroupés par doc.

Les résultats par page sont faciles. Cette requête renvoie une liste de pages correspondantes (chaque page est renvoyée dans son intégralité), plus une liste des extraits mis en évidence à partir de la page:

curl -XGET 'http://127.0.0.1:9200/my_index/page/_search?pretty=1' -d ' { "query" : { "text" : { "text" : "interesting keywords" } }, "highlight" : { "fields" : { "text" : {} } } } ' 

L’affichage des résultats regroupés par “doc” avec les surlignages du texte est un peu plus compliqué. Cela ne peut pas être fait avec une seule requête, mais un petit groupe côté client vous y conduira. Une approche pourrait être:

Etape 1: Faites une requête top-children pour trouver le parent (“doc”) dont les enfants (“page”) correspondent le mieux à la requête:

 curl -XGET 'http://127.0.0.1:9200/my_index/doc/_search?pretty=1' -d ' { "query" : { "top_children" : { "query" : { "text" : { "text" : "interesting keywords" } }, "score" : "sum", "type" : "page", "factor" : "5" } } } 

Étape 2: Collectez les identifiants “doc” de la requête ci-dessus et lancez une nouvelle requête pour obtenir les extraits de la page “correspondante”:

 curl -XGET 'http://127.0.0.1:9200/my_index/page/_search?pretty=1' -d ' { "query" : { "filtered" : { "query" : { "text" : { "text" : "interesting keywords" } }, "filter" : { "terms" : { "doc_id" : [ 1,2,3], } } } }, "highlight" : { "fields" : { "text" : {} } } } ' 

Étape 3: Dans votre application, regroupez les résultats de la requête ci-dessus par doc et affichez-les.

Avec les résultats de la recherche de la deuxième requête, vous avez déjà le texte intégral de la page que vous pouvez afficher. Pour passer à la page suivante, vous pouvez simplement le rechercher:

 curl -XGET 'http://127.0.0.1:9200/my_index/page/_search?pretty=1' -d ' { "query" : { "constant_score" : { "filter" : { "and" : [ { "term" : { "doc_id" : 1 } }, { "term" : { "page" : 2 } } ] } } }, "size" : 1 } ' 

Ou alternativement, donnez à la “page” un identifiant composé de $doc_id _ $page_num (par exemple 123_2), vous pouvez simplement récupérer cette page:

 curl -XGET 'http://127.0.0.1:9200/my_index/page/123_2 

Relation parent-enfant:

Normalement, dans ES (et la plupart des solutions NoSQL), chaque document / object est indépendant – il n’y a pas de relation réelle. En établissant une relation parent-enfant entre le “doc” et la “page”, ElasticSearch s’assure que les documents enfants (la “page”) sont stockés sur le même fragment que le document parent (le “doc”).

Cela vous permet d’exécuter la requête top-children, qui trouvera le meilleur “doc” correspondant au contenu des “pages”.

J’ai construit et conserve une application qui indexe et recherche les documents PDF 70k +. J’ai trouvé que c’était nécessairement pour extraire le texte brut des PDF, stocker le contenu en SQL et indexer la table SQL en utilisant Lucene. Sinon, la performance était horrible.

Utilisez Sunspot ou RSolr ou similaire, il gère la plupart des principaux formats de documents. Ils utilisent Solr / Lucene.