zoukankan      html  css  js  c++  java
  • Lucene4:利用Filter实现两组关键词组合查询

    1. 需求

    根据客户名称,查询客户网络上面的负面信息。如客户名称为”盐城 盐城市“,并自定义负面关键词“贪污 受贿 被曝 曝光 小三 裸照”等,则是要求将包含这些负面关键词且包含客户名称的信息查询出来。
     
    注意事项:客户名称可定义多个(10个以内),负面关键词可以定义多个(300个以内)。

    分析: 

    如果只用一个参数q去定义查询,很可能查询字符串长度会溢出,查询q应该形如:

    ((盐城 OR 盐城市) AND 贪污) OR ((盐城 OR 盐城市) AND 受贿)...... 

    所以本文采用Filter的形式来解决这一问题。
    2. 解决步骤

    步骤一:将所需要查询的客户名称、负面关键词加入到中文分词器词典文件中;(本文略)
             只有中文能够将这些关键词正确分词,其它各项操作才能顺利进行。
    步骤二:用爬虫工具将网络上的信息抓取下来后,在创建Lucene索引的时候, 将包含负面关键词的文档自定义分值(包含负面关键词越多,分值越高);(本步骤略,可以参考:Lucene4.1:运用中文分词器创建索引,给指定文本增加boost值
             这样可以保证查询时,包含负面关键词越多的文档,查询时排在越前面。
    步骤三:按客户名称查询(如:盐城 盐城市);
             正常查询输入。
    步骤四:查询时加入过滤器(Filter),过滤器的输入就是负面关键词列表;
             加入过滤器后,实现的查询结果类似于:((盐城 OR 盐城市) AND 贪污) OR ((盐城 OR 盐城市) AND 受贿)......
    步骤五:自定义高亮结果。
             因为客户名称需要高亮,负面关键词也需要高亮,所以需要自定义高亮显示。

    3. 参考源代码

    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.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.TopDocs;
    import org.apache.lucene.util.Version;
    import org.apache.lucene.search.QueryWrapperFilter;
    import org.apache.lucene.search.highlight.Highlighter;
    import org.apache.lucene.search.highlight.QueryScorer;
    import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
    import org.apache.lucene.search.highlight.SimpleSpanFragmenter;
    import org.apache.lucene.search.highlight.TokenSources;
    
    //import org.wltea.analyzer.lucene.IKAnalyzer;
    import com.chenlb.mmseg4j.Dictionary;
    import com.chenlb.mmseg4j.analysis.SimpleAnalyzer;
    
    import org.junit.Test;
    
    /**
     * 环境:Lucene 4.1版本/IKAnalyzer 2012 FF版本/mmseg4j 1.9版本
     * 
     * 根据客户名称,查询客户网络上面的负面信息。如客户名称为”盐城 盐城市“,并自定义负面关键词“贪污 受贿 被曝 曝光 小三 裸照”等,则是要求将包含这些负面关键词且包含客户名称的信息查询出来。
     * 注意事项:客户名称可定义多个(10个以内),负面关键词可以定义多个(300个以内)。
     * 
     * 分析: 如果只用一个参数q去定义查询,很可能查询字符串长度会溢出,查询q应该形如:
     * ((盐城 OR 盐城市) AND 贪污) OR ((盐城 OR 盐城市) AND 受贿)...... 
     * 所以本文采用Filter的形式来解决这一问题。
     * 
     * 解决: 
     * 步骤一:将所需要查询的客户名称、负面关键词加入到中文分词器词典文件中;(本文略)
     *     只有中文能够将这些关键词正确分词,其它各项操作才能顺利进行。
     * 步骤二:用爬虫工具将网络上的信息抓取下来后,在创建Lucene索引的时候, 将包含负面关键词的文档自定义分值(包含负面关键词越多,分值越高);(本文略,可以参考:Lucene学习笔记二(运用中文分词器创建索引,给指定文本增加boost值))
     *     这样可以保证查询时,包含负面关键词越多的文档,查询时排在越前面。
     * 步骤三:按客户名称查询(如:盐城 盐城市);
     *     正常查询输入。
     * 步骤四:查询时加入过滤器(Filter),过滤器的输入就是负面关键词列表;
     *     加入过滤器后,实现的查询结果类似于:((盐城 OR 盐城市) AND 贪污) OR ((盐城 OR 盐城市) AND 受贿)......
     * 步骤五:自定义高亮结果。
     *     因为客户名称需要高亮,负面关键词也需要高亮,所以需要自定义高亮显示。
     * @author Administrator
     *
     */
    public class ComplexDemo {
        // mmseg4j字典路径
        private static final String MMSEG4J_DICT_PATH = "C:\\solr\\mm4jdic";
        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 doUserQuery() throws Exception {
            // 实例化IKAnalyzer分词器
    //        Analyzer analyzer = new IKAnalyzer();
            
            // 实例化mmseg4j分词器
            Analyzer analyzer = new SimpleAnalyzer(dictionary);
    
            // 实例化搜索器
            final String FIELD_NAME = "webTitle";
            Directory directory = FSDirectory.open(new File(LUCENE_INDEX_DIR));
            DirectoryReader reader = DirectoryReader.open(directory);
            IndexSearcher searcher = new IndexSearcher(reader);
            QueryParser qp = new QueryParser(Version.LUCENE_41, FIELD_NAME, analyzer);
    
            // 步骤三:按客户名称查询
            String keyword = "盐城 盐城市";
            Query query = qp.parse(keyword);
            
            // 步骤四:查询时加入过滤器(Filter)......
            String negativeWord = "贪污 受贿 被曝 曝光 小三 裸照";
            Query kwQuery = qp.parse(negativeWord);
            QueryWrapperFilter qwFilter = new QueryWrapperFilter(kwQuery);
            
            // 搜索相似度最高的5条记录
            TopDocs hits = searcher.search(query, qwFilter, 5);
            System.out.println("命中:" + hits.totalHits);
    
            // 步骤五:自定义高亮代码......
            QueryScorer scorer = new QueryScorer(qp.parse(keyword + " " + negativeWord), 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);
                
                // 高亮代码输出
                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();
        }
    }

    查询输出:

    命中:13
    [<EM>曝光</EM>台]实名举报江苏<EM>盐城市</EM>阜宁县吴滩镇派出所办案无能
    <EM>盐城</EM>质监局长冯建东贪@污糜烂<EM>被曝</EM>光:包二奶、玩小姐&nbsp;还找黑客删帖遭<EM>曝光</EM>
    <EM>盐城</EM>质监局长冯建东“包二奶、招小姐、淫下属”丑行<EM>曝光</EM>
    江苏<EM>盐城市</EM>中级人民法院是什么鸟人?居然造出一个<EM>贪污</EM>大犯赵作海
    [爆 猛 料]<EM>盐城市</EM>亭湖农委下属单位领导<EM>贪污</EM>特种苗木补助款

  • 相关阅读:
    show-meeting-subject-in-meeting-room-calendar
    前端模块化——彻底搞懂AMD、CMD、ESM和CommonJS
    微软到底有多恐怖?
    Office365云流程与开发授权错误
    JQuery实现省市联动 address-picker
    我的新作品 《平虏灭寇英杰传》
    ZT:C/C++ 字符串与数字相互转换
    C016:字符串倒置
    C015:十进制转8进制
    C014:不用算术分割显示逆序三位数
  • 原文地址:https://www.cnblogs.com/nayitian/p/2918508.html
Copyright © 2011-2022 走看看