45

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

ドキュメントはさまざまな形式で存在しますが、一部は廃止されています(.docPageMaker、ハードコピー(OCR)、PDFなど)。ドキュメントを「最新の」形式に移行するための資金が利用可能であり、ハードコピーの多くはすでにPDFにOCRされています。当初はPDFが最終的な形式であると想定していましたが、提案を受け付けています(XML?) 。

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

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

アドバイスありがとうございます。

4

3 に答える 3

123

要約すると、 ElasticSearchをお勧めしますが、問題を分解して、実装方法について説明しましょう。

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

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

ElasticSearchが提供できるもの:

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

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

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

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

  1. Tika(または使い慣れたもの)を使用して、各ドキュメントからテキストを抽出します。プレーンテキストまたはHTMLのままにして、フォーマットを保持します。(XMLは忘れてください、必要ありません)。
  2. また、各ドキュメントのメタデータを抽出します:タイトル、作成者、章、言語、日付など
  3. 元のドキュメントをファイルシステムに保存し、後で提供できるようにパスを記録します
  4. ElasticSearchで、すべてのメタデータと、場合によってはチャプターのリストを含む「doc」ドキュメントにインデックスを付けます
  5. 各ページを「ページ」ドキュメントとしてインデックス付けします。これには、次のものが含まれます。

    • 「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を実行して、子( "page")がクエリに最も一致する親( "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:上記のクエリから「ドキュメント」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など)で構成されるIDを指定すると、そのページを取得できます。

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

親子関係:

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

これにより、「ページ」のコンテンツに基づいて最も一致する「ドキュメント」を見つけるtop-children-queryを実行できます。

于 2012-06-02T09:45:35.780 に答える
2

私は70k以上のPDFドキュメントにインデックスを付けて検索するアプリケーションを構築して維持しています。PDFからプレーンテキストを引き出し、その内容をSQLに格納し、Luceneを使用してSQLテーブルにインデックスを付けることが必然であることがわかりました。そうでなければ、パフォーマンスはひどいものでした。

于 2012-06-01T18:07:13.830 に答える
2

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

于 2012-06-01T18:09:40.577 に答える