Revisiter un projet au point mort et rechercher des conseils pour moderniser des milliers de "vieux" documents et les rendre disponibles via le web.
Les documents existent dans différents formats, certains obsolètes: (. Doc, PageMaker, copie papier (OCR), PDF , etc.). Des fonds sont disponibles pour migrer les documents dans un format "moderne", et bon nombre des copies papier ont déjà été OCR en PDF - nous avions initialement supposé que PDF serait le format final mais nous suis ouvert 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 renvoyer uniquement des parties (pages?) Du document entier où une recherche a été trouvée (je crois que Lucene/elasticsearch rend cela possible?!?) Cela pourrait-il être plus flexible si le contenu était entièrement XML? Si oui, comment/où stocker le XML? Directement dans la base de données ou sous forme de fichiers discrets dans le système de fichiers? Qu'en est-il des images/graphiques intégrés dans les documents?
Curieux de voir comment les autres pourraient aborder cela. Il n'y a pas de "mauvaise" réponse. Je cherche juste autant d'entrées que possible pour nous aider à continuer.
Merci pour tout conseil.
En résumé: je vais recommander ElasticSearch , mais décomposons le problème et parlons de la façon de l'implémenter:
Il y a quelques parties à cela:
Que peut fournir ElasticSearch:
Vous pouvez simplement envoyer le document entier à ElasticSearch sous forme de pièce jointe, et vous obtiendrez une recherche en texte intégral. Mais les points d'achoppement sont (4) et (5) ci-dessus: savoir où vous êtes dans un document et renvoyer des parties d'un document.
Le stockage de pages individuelles est probablement suffisant pour vos besoins où-suis-je (bien que vous puissiez également descendre au niveau du paragraphe), mais vous souhaitez les regrouper de manière à ce qu'un document soit renvoyé dans les résultats de la recherche, même si des mots clés de recherche apparaissent sur différentes pages.
Tout d'abord la partie indexation: stocker vos documents dans ElasticSearch:
Indexez chaque page en tant que document "page", qui contient:
Maintenant pour chercher. La façon dont vous procédez dépend de la façon dont vous souhaitez présenter vos résultats - par page ou groupé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 d'extraits de code en surbrillance 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 reflets du texte est un peu plus délicat. Cela ne peut pas être fait avec une seule requête, mais un petit regroupement côté client vous y mènera. Une approche pourrait être:
Étape 1: effectuez une top-children-query 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 ID "doc" de la requête ci-dessus et émettez une nouvelle requête pour obtenir les extraits des documents "page" correspondants:
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 recherche de la deuxième requête, vous disposez déjà du texte intégral de la page que vous pouvez afficher. Pour passer à la page suivante, vous pouvez simplement la 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 bien, attribuez aux documents "page" un ID 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/objet est indépendant - il n'y a pas de vraies relations. En établissant une relation parent-enfant entre le "doc" et la "page", ElasticSearch s'assure que les documents enfants (c'est-à-dire la "page") sont stockés sur le même fragment que le doc parent (le "doc").
Cela vous permet d'exécuter la top-children-query qui trouvera le "doc" correspondant le mieux en fonction du contenu des "pages".
J'ai construit et maintenu une application qui indexe et recherche 70k + PDF. 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, les performances étaient horribles.