Lucene4:创建查询,并高亮查询关键词

2019-03-27 01:06|来源: 网路

1. 要求

环境:

  Lucene 4.1版本/IKAnalyzer 2012 FF版本/mmseg4j 1.9版本
功能:
  1).高亮查询演示

注意:

此篇文章开始,索引目录将不再使用示范目录,而是使用真实的数据。即LUCENE_INDEX_DIR = "C:\\lucene\\data"改到了LUCENE_INDEX_DIR = "C:\\solr\\news\\data\\index"。

2. 实现代码

package com.clzhang.sample.lucene;

import java.io.*;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;

import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.highlight.Fragmenter;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleSpanFragmenter;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.search.highlight.TokenSources;
import org.apache.lucene.util.Version;

import com.chenlb.mmseg4j.Dictionary;
import com.chenlb.mmseg4j.analysis.SimpleAnalyzer;
import com.chenlb.mmseg4j.analysis.ComplexAnalyzer;

import org.junit.Test;

/**
 * 环境:Lucene 4.1版本/IKAnalyzer 2012 FF版本/mmseg4j 1.9版本
 * 功能:
 * 1.高亮查询演示
 * @author Administrator
 *
 */
public class HighlightDemo {
    // mmseg4j字典路径
    private static final String MMSEG4J_DICT_PATH = "C:\\solr\\news\\conf";
    private static Dictionary dictionary = Dictionary.getInstance(MMSEG4J_DICT_PATH);
    
    // Lucene索引存放路径 
    private static final String LUCENE_INDEX_DIR = "C:\\solr\\news\\data\\index";

    @Test
    public void testHighlighting() throws Exception {
        // 独立测试Highlighting的代码
        String text = "台保钓人士拟起诉日当局 感谢大陆海监船驰援";
        TermQuery query = new TermQuery(new Term("title", "当局"));

        TokenStream tokenStream = new ComplexAnalyzer(dictionary).tokenStream(
                "title", new StringReader(text));
        QueryScorer scorer = new QueryScorer(query, "title");
        Fragmenter fragmenter = new SimpleSpanFragmenter(scorer);
        Highlighter highlighter = new Highlighter(scorer);
        highlighter.setTextFragmenter(fragmenter);
        String hlText = highlighter.getBestFragment(tokenStream, text);
        
        System.out.println(hlText);
        System.out.println("--------------------------");
    }
    
    @Test
    public void doHighlightQuery() throws Exception {
        // 实例化IKAnalyzer分词器
//        Analyzer analyzer = new IKAnalyzer();
        
        // 实例化mmseg4j分词器
        Analyzer analyzer = new SimpleAnalyzer(dictionary);

        // 实例化搜索器
        Directory directory = FSDirectory.open(new File(LUCENE_INDEX_DIR));
        DirectoryReader reader = DirectoryReader.open(directory);
        IndexSearcher searcher = new IndexSearcher(reader);
        final String FIELD_NAME = "webTitle";
        String keyword = "记者";

        // 使用QueryParser查询分析器构造Query对象
        QueryParser qp = new QueryParser(Version.LUCENE_41, FIELD_NAME, analyzer);
        Query query = qp.parse(keyword);
        
        // 搜索相似度最高的5条记录
        TopDocs hits = searcher.search(query, 5);
        System.out.println("命中:" + hits.totalHits);

        // 高亮代码1
        QueryScorer scorer = new QueryScorer(query, FIELD_NAME);
        // 下面是指定高亮代码样式的代码
        SimpleHTMLFormatter simpleHtmlFormatter = new SimpleHTMLFormatter("<EM>", "</EM>"); 
        Highlighter highlighter = new Highlighter(simpleHtmlFormatter, scorer);
        highlighter.setTextFragmenter(
                       new SimpleSpanFragmenter(scorer));

        // 输出结果
        for (ScoreDoc scoreDoc : hits.scoreDocs) {
            Document doc = searcher.doc(scoreDoc.doc);
            String title = doc.get(FIELD_NAME);
            
            // 高亮代码2
            TokenStream stream = TokenSources.getAnyTokenStream(
                    searcher.getIndexReader(), scoreDoc.doc, FIELD_NAME, doc, analyzer);
            String fragment = highlighter.getBestFragment(stream, title);
            System.out.println(fragment);
        }
        reader.close();
        directory.close();

        System.out.println("--------------------------");
    }
}

输出:

台保钓人士拟起诉日<B>当局</B> 感谢大陆海监船驰援
--------------------------
命中:125
浙江杭州一男子涉嫌殴打<EM>记者</EM>被警方抓获
领导快看;<EM>记者</EM>曝光!
[视频]节前聚焦烟花爆竹安全 居民楼内存花炮 <EM>记者</EM>举报无人监管 20130203
老夫看过<EM>记者</EM>关于肖某勒索的调查视频,可以说,“胁从犯罪”的证据极为明显——问题就在于,曾经处理方哦,算是结了案,再次处理,法理上有疑问
<EM>记者</EM>调查:重庆忠县一桩疑窦重生的受贿案(转载)
--------------------------


转自:http://www.cnblogs.com/nayitian/archive/2013/01/25/2876900

相关问答

更多
  • Mysql的高级查询[2023-01-24]

    这个如果必须一条语句写出来,貌似没什么单独的高级语句或者函数可以搞定。 我想类似这种需求一般这种应该是超大数据量。 思路就是把key列全部查询出来,导入到文本,再去计算每个的次数,这个用计算次数可以用map/reduce经典wordcount程序在hadoop上跑出来。 如果不在乎数据量的话, 写个存储过程,里面套用个循环把不定长的key列以逗号为分隔符,每个分割为一条记录,统统存入临时表后,count group by 搞定。
  • Lucene是什么?[2022-06-24]

    Lucene针对中文单字为词,“我是学生”在standardAnalyzer分割下,分为“我”,“是”,“学”,“生”。 车东做了CJKAnalyzer可以分为“我是”,“是学”,“学生”。 你也可以用Dijkstra算法来自己做一个,源代码向家立要,他和我写过《Lucene分析与应用》,他会告诉你去如何下载这个代码,这种分词都是有经验值的,也就是说“学生”,已经是分割过的,就是有字典存在。 不配合字典你再想一想,自然语言是什么?是人类的交谈工具吧,有没有规律哪?频率,位置依赖关系,但是不管如何,人类自己要 ...
  • 还没有,请参阅上游的https://secure.phabricator.com/T5132 。 Not yet, see https://secure.phabricator.com/T5132 in the upstream.
  • 我认为你想要的是关键短语提取,你可以这样做,例如首先用它的PoS标签标记每个单词,然后在PoS标签上应用某种正则表达式,将有趣的单词加入关键短语。 import nltk from nltk import pos_tag from nltk import tokenize def extract_phrases(my_tree, phrase): my_phrases = [] if my_tree.label() == phrase: my_phrases.append(my_ ...
  • 根据您的Hive版本,尝试包装反引号中设置的列名,例如: SELECT * FROM activitytable WHERE `set` = 'vmXXXX'; Depending on your Hive version, try wrapping the column name set in backticks, like: SELECT * FROM activitytable WHERE `set` = 'vmXXXX';
  • 你可以制作一套想要消除的“停止词”(也许可以从NLTK的停止词语体中复制一遍,取决于你对你需要支持的各种自然语言的熟悉程度),然后申请非常简单。 例如,如果你有一个组成句子的单词列表(为了简单起见,标点符号和小写的标签), [word for word in sent if word not in sw] ,你需要制作一个非停用词列表 - 几乎不容易,对吧? 要首先使用标准库中的re模块获取sent列表,如果sentstring是包含您正在处理的句子的字符串,则re.findall(r'\w+', sent ...
  • 我为你搜索谷歌: 可以分别使用Zend_Search_Lucene_Search_QueryParser::setDefaultOperator($operator)和Zend_Search_Lucene_Search_QueryParser::getDefaultOperator()方法设置或检索默认布尔运算符。 这些方法使用Zend_Search_Lucene_Search_QueryParser::B_AND和Zend_Search_Lucene_Search_QueryParser::B_OR常量。 ...
  • 显然它是查询解析器中的一个错误 (相当老btw)。 我建议您为该问题添加注释或打开一个新注释以确认它仍然在ZF的xx版本中发生。 Apparently it is a bug in the query parser (quite old btw). I would suggest that you either add a comment to that issue or open a new one to confirm that it is still happening in version x.x ...
  • 热图的文档字符串告诉您: annot_kws :键,值映射的dict,当annot为True时ax.text的可选关键字参数。 cbar_kws :键,值映射的dict, fig.colorbar的可选关键字参数。 这意味着这些字典将关键字参数直接传递给底层的matplotlib结构。 annot_kws是annot_kws的关键字, cbar_kws是cbar_kws的关键字。 因此,为了找出可能的参数,您必须查看这些对象的matplotlib文档。 这是figure.colorbar的文档。 这是axi ...
  • 尝试这个。 希望能帮到你 $string='he is good'; $keyWords=explode(' ',$string); $searchQuery=''; foreach ($keyWords as $word) { $word = trim($word); if ($word) { $searchQuery = $searchQuery . "find_in_set('$word', trim(key_words)) > 0 or "; } } $sea ...