2017-06-20 24 views
0

Lucene RAMDirectoryを作成して、さまざまなソースからデータを収集し、迅速に検索できるようにしました。さまざまなアナライザーとインデックス戦略を理解するのに数時間を費やしましたが、クエリ結果が期待通りではない場合もあります。ここでLucene BooleanQueryの間違った結果

はデモクラスです:

class LuceneDemo { 

    static final String ANIMAL = "animal"; 
    static final String PERSON = "person"; 

    private StandardAnalyzer analyzer = new StandardAnalyzer(); 

    private IndexSearcher searcher; 
    private IndexWriter writer; 

    LuceneDemo() { 
     Directory ramDirectory = new RAMDirectory(); 
     IndexWriterConfig config = new IndexWriterConfig(analyzer); 
     try { 
      writer = new IndexWriter(ramDirectory, config); 

      addDocument(createDocument(PERSON, "DR-(frankenstein)")); 
      addDocument(createDocument(ANIMAL, "gray fox")); 
      addDocument(createDocument(ANIMAL, "island fox")); 

      writer.close(); 
      IndexReader reader = DirectoryReader.open(ramDirectory); 
      searcher = new IndexSearcher(reader); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    private Document createDocument(String type, String value) { 
     Document document = new Document(); 
     document.add(new TextField("type", type, Field.Store.YES)); 
     document.add(new TextField("name", value, Field.Store.YES)); 
     document.add(new StringField("name", value, Field.Store.YES)); 
     return document; 
    } 

    private void addDocument(Document document) { 
     try { 
      writer.addDocument(document); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    List<String> getDocuments(String type, String value) { 
     value = "*" + QueryParser.escape(value) + "*"; 
     try { 
      QueryParser queryParser = new QueryParser("name", analyzer); 
      queryParser.setAllowLeadingWildcard(true); 
      queryParser.setDefaultOperator(QueryParser.Operator.AND); 

      BooleanQuery.Builder query = new BooleanQuery.Builder(); 
      query.add(new TermQuery(new Term("type", type)), BooleanClause.Occur.MUST); 
      query.add(queryParser.parse(value), BooleanClause.Occur.MUST); 

      TopDocs docs = searcher.search(query.build(), 10); 

      return Arrays.stream(docs.scoreDocs).map(scoreDoc -> { 
       try { 
        return searcher.doc(scoreDoc.doc).get("name"); 
       } catch (IOException e) { 
        return ""; 
       } 
      }).collect(Collectors.toList()); 
     } catch (ParseException | IOException e) { 
      e.printStackTrace(); 
     } 
     return Collections.emptyList(); 
    } 
} 

私は「牛」、「灰色キツネ」かを検索すると、「 - (フランケンシュタイン)」、コードはかなりうまく動作します。しかし、私は「DR-(フランケンシュタイン)」の結果はありません。私は何が間違っていたのか分かりません。だから、どんな提案も大歓迎です。

// OK 
luceneDemo.getDocuments(LuceneDemo.ANIMAL, "ox").forEach(System.out::println); 
luceneDemo.getDocuments(LuceneDemo.ANIMAL, "gray fox").forEach(System.out::println); 
luceneDemo.getDocuments(LuceneDemo.PERSON, "-(frankenstein)").forEach(System.out::println); 

// NOT OK 
luceneDemo.getDocuments(LuceneDemo.PERSON, "DR-(frankenstein)").forEach(System.out::println); 

答えて

0

これはあなたの文書がインデックス化されている方法です -

  1. のdoc#1 タイプ:人名前:DR :フランケンシュタイン:DR-(フランケンシュタイン)(注: StringFieldはトークン化されておらず、小文字に変換されません)
  2. doc#2 タイプ:動物:グレー:キツネ:灰色キツネ
  3. DOC#3 タイプ:動物:島:キツネ:島キツネ

に関係なく、基本的にStringFieldのインデックスフィールド - トークン化せずに、ケースを下げます。読者はStandardAnalyzerを使用しており、すべての検索で大文字小文字を低くします。 "DR-(frankenstein)"を検索すると、一致しない "dr-(frankenstein)"が検索されます。

StandardAnalyzerを使用してコードを動作させるには、StringFieldに小文字のインデックスを付ける必要があります。

document.add(new StringField("name", value.toLowerCase(), Field.Store.YES)); 
+1

ありがとうございました!私はカスタムアナライザーを作成し、Stringフィールドを小文字で索引付けしました。今私は正しい結果を持っている! – aszidien