2016-11-10 2 views
0

Luceneを使用して(Hibernate Searchを使用して)照会したい企業と人のデータベースがあります。検索機能はオートコンプリートスタイルのルックアップとして実装されています。このルックアップでは、Webページがユーザーの入力時に一致を提案します。ルーネンインデックスを1文字で照会する(例:人物イニシャル)

一部の企業および人々は、イニシャルを使用して識別されます。

  • G & H土木
  • JG VAN DER MERWEは

私は(ユーザーが文字のカップルを入力した後に試合を取得を開始したいのですが、彼らはより多くのテキストを追加すると、次第に検索を洗練しますおそらくスペースを含む)。私はいくつかの異なる分野に質問しています。名前、商品名、ID番号、電話番号などを使用して、ユーザーが名前、ID番号、商品名またはセル番号の一部を入力できるようにします。

しかし、G & Hのような用語がドキュメントに一致するようにインデックスとクエリを設定する際に問題があります。 CIVILのような用語を使用すると、多くの一致があります。しかし、間に空白がある単一の文字は何も一致しません。

最後の行で以下のテストが失敗します。アナライザー、トークナイザー、フィルター&の組み合わせを使用する必要があります。

@Test 
public void testSearching() throws Exception { 
    Analyzer analyzer = new ReusableAnalyzerBase() { 
     @Override 
     protected TokenStreamComponents createComponents(String fieldName, Reader reader) { 
      StandardTokenizer tokenizer = new StandardTokenizer(Version.LUCENE_36, reader); 
      LowerCaseFilter lowerCaseFilter = new LowerCaseFilter(Version.LUCENE_36, tokenizer); 
      NGramTokenFilter filter = new NGramTokenFilter(lowerCaseFilter, 3, 20); 
      return new TokenStreamComponents(tokenizer, filter); 
     } 
    }; 
    Directory ramDirectory = new RAMDirectory(); 

    IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_36, analyzer); 
    IndexWriter w = new IndexWriter(ramDirectory, config); 

    Document doc = new Document(); 
    doc.add(new Field("id", "819", Field.Store.YES, Field.Index.NOT_ANALYZED)); 
    doc.add(new Field("particulars.registeredName", "G & H CIVIL ENGINEERING", Field.Store.NO, Field.Index.ANALYZED)); 

    w.addDocument(doc); 
    w.close(); 

    // search 
    int numberOfHits = 200; 
    TopScoreDocCollector collector = TopScoreDocCollector.create(numberOfHits, true); 
    IndexSearcher searcher = new IndexSearcher(IndexReader.open(ramDirectory)); 

    PhraseQuery q = new PhraseQuery(); 
    q.add(new Term("particulars.registeredName", "civil")); 
    searcher.search(q, collector); 
    ScoreDoc[] hits = collector.topDocs().scoreDocs; 
    assertThat(hits.length, greaterThan(0)); 

    PhraseQuery phraseQuery = new PhraseQuery(); 
    phraseQuery.add(new Term("particulars.registeredName", "g & h")); 
    searcher.search(q, collector); 
    hits = collector.topDocs().scoreDocs; 
    assertThat(hits.length, greaterThan(0)); // this fails - no matches 

私はLuceneを使い慣れています。どのポインタもわかります。

答えて

0

あなたの特定の問題は、コレクタを再利用していることと関連している可能性があります。これはステートフルであり、一度だけ使用するように設計されています。あなたの新しいコレクターを使用して2番目のクエリは、トリックを行う必要があります。

しかしは、Hibernateの検索であなたは多くのLuceneの内部に触れることになっていないことに注意してください:休止検索が自動的にインデックス作成時に、あなたのエンティティからのLucene文書を導出し、クエリ時に、必要に応じて、インデックスの読者やコレクターを構築します。 Lucene/Hibernate Searchが初めての方は、Luceneを直接使用しないでください。Luceneは強力ですが、使いやすいツールではありません。

これは、ドキュメントを手動で構築するのではなく、注釈付き(またはプログラムでマップされた)エンティティを使用することを意味します。 the documentation、特にsection about entity mappingsection about analysisを参照してください。

また、クエリするときはthe Hibernate Search DSLを使用してください。おそらく生のLuceneクエリを構築するよりも簡単になるでしょう。また、クエリが構築されたときに、Hibernate Searchにretrieve the resultsを簡単に問い合わせることもできます。

関連する問題