web-dev-qa-db-ja.com

数千のドキュメントの検索可能なアーカイブのベストプラクティス(pdfまたはxml)

行き詰まったプロジェクトを再訪し、何千もの「古い」ドキュメントを近代化し、ウェブ経由で利用できるようにするためのアドバイスを探しています。

文書はさまざまな形式で存在し、一部は廃止されました:(。docPageMaker、hardcopy(OCR)、[〜#〜] pdf [〜#〜]など)。ドキュメントを「モダン」形式に移行するための資金が用意されており、ハードコピーの多くは既にPDFにOCRされています-元々PDFが最終形式になると想定していましたが、 '提案を受け入れています(XML?)。

すべてのドキュメントが共通の形式になったら、そのコンテンツを利用可能にし、Webインターフェイス経由で検索可能にします。検索の「ヒット」が見つかったドキュメント全体の一部(ページ?)のみを返す柔軟性が必要です(Lucene/elasticsearchでこれが可能になると思いますか?!?)コンテンツがすべてXMLであれば、より柔軟になりますか?もしそうなら、どのように/どこにXMLを保存しますか?データベース内に直接、またはファイルシステム内の個別のファイルとして?ドキュメントに埋め込まれた画像/グラフはどうですか?

他の人がどのようにこれにアプローチするのか興味があります。 「間違った」答えはありません。私は、できるだけ多くの入力を求めて進めています。

アドバイスをありがとう。

44
Meltemi

要約すると、私は ElasticSearch を推奨するつもりですが、問題を分析し、それを実装する方法について話しましょう。

これにはいくつかの部分があります。

  1. ドキュメントからテキストを抽出してインデックス化可能にする
  2. このテキストを全文検索として利用可能にする
  3. 強調表示されたドキュメントのスニペットを返す
  4. ドキュメントのどこでこれらのスニペットがページングを許可することがわかっているかを知る
  5. 完全なドキュメントを返す

ElasticSearchが提供できるもの:

  1. ElasticSearch(Solrなど)は Tika を使用して、さまざまなドキュメントからテキストとメタデータを抽出します formats
  2. それは、明らかに、強力な全文検索を提供します。適切な言語で各ドキュメントを分析し、特定のフィールド(たとえば、コンテンツよりも重要なタイトル)、ngramsなどの関連性を高める、標準のLuceneスタッフなどを分析するように構成できます。
  3. 各検索結果に対して 強調表示されたスニペット を返すことができます
  4. これらのスニペットがドキュメントのどこにあるかはわかりません
  5. 元のドキュメントを attachment として保存するか、抽出したテキストを保存して返すことができます。ただし、ページではなくドキュメント全体が返されます。

ドキュメント全体を添付ファイルとしてElasticSearchに送信するだけで、全文検索が可能になります。しかし、こだわりのポイントは上記の(4)と(5)です:あなたがドキュメントのどこにいるかを知り、ドキュメントの一部を返します。

個々のページを保存することは、おそらくwhere-am-Iの目的には十分です(ただし、段落レベルに等しく下げることもできます)が、検索キーワードが表示されても、検索結果にドキュメントが返されるようにグループ化する必要があります別のページに。

最初にインデックス作成部分:ElasticSearchにドキュメントを保存します:

  1. Tika(または使い慣れたもの)を使用して、各ドキュメントからテキストを抽出します。プレーンテキストのままにするか、一部の書式を保持するためにHTMLのままにします。 (XMLを忘れて、それを必要としません)。
  2. 各ドキュメントのメタデータも抽出します:タイトル、著者、章、言語、日付など
  3. オリジナルのドキュメントをファイルシステムに保存し、後で提供できるようにパスを記録します
  4. ElasticSearchで、すべてのメタデータと、場合によっては章のリストを含む「doc」docのインデックスを作成します
  5. 以下を含む「ページ」ドキュメントとして各ページのインデックスを作成します。

    • 親フィールド これには「doc」docのIDが含まれます(以下の「親子関係」を参照)
    • テキスト
    • ページ番号
    • 多分章のタイトルまたは番号
    • 検索可能にしたいメタデータ

今すぐ検索します。これを行う方法は、ページごと、またはドキュメントごとにグループ化して、結果の表示方法によって異なります。

ページごとの結果は簡単です。このクエリは、一致するページのリスト(各ページが完全に返される)と、ページから強調表示されたスニペットのリストを返します。

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

「doc」でグループ化された結果をテキストのハイライトとともに表示するのは少し面倒です。単一のクエリで行うことはできませんが、クライアント側で少しグループ化するとそこに到達します。 1つのアプローチは次のとおりです。

ステップ1: top-children-query を実行して、クエリに最も一致する子( "ページ")を持つ親( "doc")を見つけます。

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"
      }
   }
}

ステップ2:上記のクエリから「doc」IDを収集し、新しいクエリを発行して、一致する「ページ」ドキュメントからスニペットを取得します。

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" : {}
      }
   }
}
'

ステップ3:アプリで、上記のクエリの結果をドキュメントごとにグループ化し、表示します。

2番目のクエリの検索結果では、表示可能なページのフルテキストが既にあります。次のページに移動するには、検索するだけです。

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
}
'

または、「ページ」ドキュメントに$doc_id _ $page_num(例123_2)そのページを取得できます:

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

親子関係:

通常、ES(およびほとんどのNoSQLソリューション)では、各ドキュメント/オブジェクトは独立しています-実際の関係はありません。 「doc」と「ページ」の間に親子関係を確立することにより、ElasticSearchは子ドキュメント(つまり「ページ」)が親ドキュメント(「doc」)と同じシャードに保存されるようにします。

これにより、 top-children-query を実行して、「ページ」のコンテンツに基づいて最適な「doc」を検索できます。

114
DrTech

70k + PDFドキュメント。インデックスを作成して検索するアプリケーションを作成し、保守しました。PDFからプレーンテキストを引き出し、SQLに内容を保存し、SQLテーブルにインデックスを付けることが必要でした。そうでなければ、パフォーマンスは恐ろしいものでした。

2
Josh Siok

Sunspot または RSolr などを使用して、ほとんどの主要なドキュメント形式を処理します。彼らはSolr/Luceneを使用します。

2
Dave Newton