使用lucene进行前缀搜索

时间:2015-04-17 18:53:08

标签: java lucene

我正在尝试使用lucene搜索功能进行自动完成。我有下面的代码,它通过查询前缀进行搜索,但同时它也给了我包含该单词的所有句子,而我希望它只显示以该前缀开头的句子或单词。

ex: m --holiday m ansion船屋 - 眼睛 m uscles - m 有史以来的卵子 - 的 achine

我希望它只显示最后2个查询。如何做到这里也被困在这里我也是lucene的新手。请任何人帮助我。提前谢谢。

       addDoc(IndexWriter w, String title, String isbn) throws IOException {
    Document doc = new Document();
    doc.add(new Field("title", title, Field.Store.YES, Field.Index.ANALYZED));

    // use a string field for isbn because we don't want it tokenized
    doc.add(new Field("isbn", isbn, Field.Store.YES, Field.Index.ANALYZED));
    w.addDocument(doc);

 }

主:

    try {
        // 0. Specify the analyzer for tokenizing text.
        //    The same analyzer should be used for indexing and searching
        StandardAnalyzer analyzer = new StandardAnalyzer();

        // 1. create the index
        Directory index = FSDirectory.open(new File(indexDir));
        IndexWriter writer = new IndexWriter(index, new StandardAnalyzer(Version.LUCENE_30), true, IndexWriter.MaxFieldLength.UNLIMITED); //3

        for (int i = 0; i < source.size(); i++) {
            addDoc(writer, source.get(i), + (i + 1) + "z");
        }

        writer.close();


        // 2. query
      Term term = new Term("title", querystr);
      //create the term query object
     PrefixQuery query = new PrefixQuery(term);



        // 3. search
        int hitsPerPage = 20;
        IndexReader reader = IndexReader.open(index);
        IndexSearcher searcher = new IndexSearcher(reader);
        TopScoreDocCollector collector =      TopScoreDocCollector.create(hitsPerPage, true);
        searcher.search(query, collector);
        ScoreDoc[] hits = collector.topDocs().scoreDocs;

        // 4. Get results
        for (int i = 0; i < hits.length; ++i) {
            int docId = hits[i].doc;
            Document d = searcher.doc(docId);

            System.out.println(d.get("title"));


        }

        reader.close();


    } catch (Exception e) {
        System.out.println("Exception (LuceneAlgo.getSimilarString()) : " + e);
    }


}


 }

2 个答案:

答案 0 :(得分:1)

如果我理解您的方案正确,您希望在标题字段上自动填充。

解决方案是有两个字段:一个是分析的,是为了能够对它进行查询,一个是非分析的,可以将标题编入索引,而不会将它们分成单个术语。 您的自动完成逻辑应针对未分析字段发出前缀查询,以仅匹配第一个字。您的术语查询应针对标题中匹配的分析字段发布。

我希望这是有道理的。

答案 1 :(得分:0)

我看到两个解决方案:

    根据Yahnoosh的建议
  1. ,保存标题字段两次,一次作为TextField(=已分析),一次作为StringField(未分析)

  2. 将其保存为TextField,但在查询时使用SpanFirstQuery

  3. // 2. query
    Term term = new Term("title", querystr);
    //create the term query object
    PrefixQuery pq = new PrefixQuery(term);
    SpanQuery wrapper = new SpanMultiTermQueryWrapper<PrefixQuery>(pq);
    Query final = new SpanFirstQuery(wrapper, 1);