lucene中文分词以及高亮显示

这篇博客介绍一下如何在Lucene中使用中文分词以及高亮显示查询结果中与搜索匹配的部分

1.在pom.xml中加入相关依赖

    <!-- 高亮显示 -->
    <dependency>
      <groupId>org.apache.lucene</groupId>
      <artifactId>lucene-highlighter</artifactId>
      <version>7.2.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.lucene/lucene-analyzers-smartcn -->
    <!-- 中文分词 -->
    <dependency>
      <groupId>org.apache.lucene</groupId>
      <artifactId>lucene-analyzers-smartcn</artifactId>
      <version>7.2.0</version>
    </dependency>

2.准备用于建立索引的中文数据,这里选择了几部笔者喜欢的日剧

    //准备的中文测试数据
    final String[] ids = {"1", "2", "3"};
    final String[] names = {"非自然死亡(unnatural)", "为了N", "白夜行"};
    final String[] desc = {
            "《非自然死亡》(日语名:アンナチュラル)是日本TBS电视台播出的医学悬疑剧,由冢原亚由子、竹村谦太郎、村尾嘉昭执导,野木亚纪子编剧,石原里美主演,洼田正孝、井浦新等共演,于2018年1月12日在日本开播。 [1] \n" +
            "该剧讲述了在“非自然死亡原因研究所”任职的法医三澄美琴与同事们一起探查非正常死亡者的真正死因,从而改变现实世界的故事 [2]  。",
            "《为了N》是改编自凑佳苗的同名小说的一部推理纯爱电视剧。由日本TBS电视台于2014年10月17日出品并首播。冢原あゆ子、山本刚义执导,奥寺佐渡子编剧,荣仓奈奈、洼田正孝、贺来贤人、小出惠介、三浦友和等主演。\n" +
                    "该剧登场人物有一个共同点,那便是他们名字的首字母都是“N”。故事刻画了这些N们如何相遇、相爱、并犯下罪行的故事 [1]  。",
            "《白夜行》是日本2006年TBS电视台播出的电视剧,根据东野圭吾同名推理小说《白夜行》改编,由森下佳子编剧,山田孝之、绫濑遥主演。 [1-2] \n" +
                    "该剧讲述了一对有着悲惨命运的少年少女,14年以来以相当残酷、孤独、单纯的灵魂相爱着却无法相守的故事。"
    };

3.建立索引,这里的关键点是使用lucene-analyzers-smartcn依赖提供的SmartChineseAnalyzer替代之前使用的英文分词器

/**
     * 在指定的目录下创建索引
     */
    @Test
    public void createIndex() throws Exception{
        Directory directory = FSDirectory.open(Paths.get(indexDir));

        //使用中文分词器而不是英文分词器StandardsAnalyser
        SmartChineseAnalyzer chineseAnalyzer = new SmartChineseAnalyzer();

        IndexWriterConfig config = new IndexWriterConfig(chineseAnalyzer);

        IndexWriter writer = new IndexWriter(directory, config);

        for(int i = 0; i < ids.length; i++){
            Document doc = new Document();
            doc.add(new StringField("id", ids[i], Field.Store.YES));
            doc.add(new StringField("name", names[i], Field.Store.YES));
            doc.add(new TextField("desc", desc[i], Field.Store.YES));

            writer.addDocument(doc);
        }

        writer.close();
    }
使用luke查看desc索引的分词情况,可以看到分词的结果还是很智能的
![分词结果](https://img-blog.csdn.net/20180916211915966?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3NTU2NDQ0/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

4.对索引进行查询并高亮显示,注意传入QueryParser传入的分词器也需要是中文分词器,高亮显示部分的api使用请参照代码注释。

 /**
     * 测试高亮
     * @throws Exception
     */
    @Test
    public void TestHignLighter() throws Exception{
        Directory directory = FSDirectory.open(Paths.get(indexDir));
        IndexReader reader = DirectoryReader.open(directory);

        IndexSearcher searcher = new IndexSearcher(reader);
        Analyzer analyzer = new SmartChineseAnalyzer();
        QueryParser queryParser = new QueryParser("desc", analyzer);
        String queryExpression = "白夜";
        Query query = queryParser.parse(queryExpression);

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

        QueryScorer queryScorer = new QueryScorer(query);//根据查询的匹配度返回摘要
        Fragmenter fragmenter = new SimpleSpanFragmenter(queryScorer);
        //指定高亮部分的显示样式
        SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<b><font color='red'>","</font></b>");
        Highlighter highlighter = new Highlighter(formatter, queryScorer);
        highlighter.setTextFragmenter(fragmenter);

        System.out.println("查询到了"+docs.totalHits+"条记录");
        for(ScoreDoc doc : docs.scoreDocs){
            System.out.println("id:"+searcher.doc(doc.doc).get("id"));
            System.out.println("name:"+searcher.doc(doc.doc).get("name"));
            String desc = searcher.doc(doc.doc).get("desc");
            System.out.println("desc:"+desc);
            //显示bestMatch(摘要)
            TokenStream tokenStream = analyzer.tokenStream("desc", new StringReader(desc));
            System.out.println("best_match:"+highlighter.getBestFragment(tokenStream, desc));
        }

        reader.close();
    }

猜你喜欢

转载自blog.csdn.net/m0_37556444/article/details/82729793