分享

基于lucene的案例开发17:查询语句创建PackQuery

gefieder 2015-4-15 11:35:26 发表于 连载型 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 1 15032
本帖最后由 nettman 于 2015-4-16 22:36 编辑
问题导读:
1、如何进行通配符检索?
2、如何定义范围搜索?
3、PackQuery类的构造方法,最好是手动指定分词器还是使用索引的分词器?为什么?




接上篇:基于lucene的案例开发16:实时索引的修改

在之前的《基于lucene的案例开发:Query查询》这篇博客中对实际开发过程中比较常见的Query做了简单的介绍,这里就介绍下具体的代码实现。查看最新代码点击这里或访问 http://www.llwjy.com/source/com.lulei.lucene.query.PackQuery.html
  1.      /**   
  2.      *@Description:  创建查询Query   
  3.      */   
  4.     package com.lulei.lucene.query;   
  5.       
  6.     import java.io.IOException;  
  7.     import java.io.StringReader;  
  8.     import java.util.ArrayList;  
  9.       
  10.     import org.apache.lucene.analysis.Analyzer;  
  11.     import org.apache.lucene.analysis.TokenStream;  
  12.     import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;  
  13.     import org.apache.lucene.index.Term;  
  14.     import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;  
  15.     import org.apache.lucene.queryparser.classic.ParseException;  
  16.     import org.apache.lucene.queryparser.classic.QueryParser;  
  17.     import org.apache.lucene.search.BooleanClause.Occur;  
  18.     import org.apache.lucene.search.BooleanQuery;  
  19.     import org.apache.lucene.search.NumericRangeQuery;  
  20.     import org.apache.lucene.search.PhraseQuery;  
  21.     import org.apache.lucene.search.PrefixQuery;  
  22.     import org.apache.lucene.search.Query;  
  23.     import org.apache.lucene.search.TermQuery;  
  24.     import org.apache.lucene.search.TermRangeQuery;  
  25.     import org.apache.lucene.search.WildcardQuery;  
  26.     import org.apache.lucene.util.Version;  
  27.       
  28.     import com.lulei.lucene.index.manager.IndexManager;  
  29.       
  30.       
  31.     public class PackQuery {  
  32.         //分词器  
  33.         private Analyzer analyzer;  
  34.         //使用索引中的分词器  
  35.         public PackQuery(String indexName) {  
  36.             analyzer = IndexManager.getIndexManager(indexName).getAnalyzer();  
  37.         }  
  38.         //使用自定义分词器  
  39.         public PackQuery(Analyzer analyzer) {  
  40.             this.analyzer = analyzer;  
  41.         }  
  42.       
  43.         /**
  44.          * @param key
  45.          * @param fields
  46.          * @return Query
  47.          * @throws ParseException
  48.          * @Author: lulei   
  49.          * @Description: 查询字符串匹配多个查询域
  50.          */  
  51.         public Query getMultiFieldQuery(String key, String[] fields) throws ParseException{  
  52.             MultiFieldQueryParser parse = new MultiFieldQueryParser(Version.LUCENE_43, fields, analyzer);  
  53.             Query query = null;  
  54.             query = parse.parse(key);  
  55.             return query;  
  56.         }  
  57.          
  58.         /**
  59.          * @param key
  60.          * @param field
  61.          * @return Query
  62.          * @throws ParseException
  63.          * @Author: lulei   
  64.          * @Description: 查询字符串匹配单个查询域
  65.          */  
  66.         public Query getOneFieldQuery(String key, String field) throws ParseException{  
  67.             if (key == null || key.length() < 1){  
  68.                 return null;  
  69.             }  
  70.             QueryParser parse = new QueryParser(Version.LUCENE_43, field, analyzer);  
  71.             Query query = null;  
  72.             query = parse.parse(key);  
  73.             return query;  
  74.         }  
  75.          
  76.         /**
  77.          * @param key
  78.          * @param fields
  79.          * @param occur
  80.          * @return Query
  81.          * @throws IOException
  82.          * @Author: lulei   
  83.          * @Description: 查询字符串、多个查询域以及查询域在查询语句中的关系
  84.          */  
  85.         public Query getBooleanQuery(String key, String[] fields, Occur[] occur) throws IOException{  
  86.             if (fields.length != occur.length){  
  87.                 System.out.println("fields.length isn't equals occur.length, please check params!");  
  88.                 return null;  
  89.             }  
  90.             BooleanQuery query = new BooleanQuery();  
  91.             TokenStream tokenStream = analyzer.tokenStream("", new StringReader(key));  
  92.             ArrayList<String> analyzerKeys = new ArrayList<String>();  
  93.             while(tokenStream.incrementToken()){  
  94.                 CharTermAttribute term = tokenStream.getAttribute(CharTermAttribute.class);  
  95.                 analyzerKeys.add(term.toString());  
  96.             }  
  97.             for(int i = 0; i < fields.length; i++){  
  98.                 BooleanQuery queryField = new BooleanQuery();  
  99.                 for(String analyzerKey : analyzerKeys){  
  100.                     TermQuery termQuery = new TermQuery(new Term(fields[i], analyzerKey));  
  101.                     queryField.add(termQuery, Occur.SHOULD);  
  102.                 }  
  103.                 query.add(queryField, occur[i]);  
  104.             }  
  105.             return query;  
  106.         }  
  107.          
  108.         /**
  109.          * @param querys
  110.          * @param occur
  111.          * @return Query
  112.          * @Author: lulei   
  113.          * @Description: 组合多个查询,之间的关系由occur确定
  114.          */  
  115.         public Query getBooleanQuery(ArrayList<Query> querys, ArrayList<Occur> occurs){  
  116.             if (querys.size() != occurs.size()){  
  117.                 System.out.println("querys.size() isn't equals occurs.size(), please check params!");  
  118.                 return null;  
  119.             }  
  120.             BooleanQuery query = new BooleanQuery();  
  121.             for (int i = 0; i < querys.size(); i++){  
  122.                 query.add(querys.get(i), occurs.get(i));  
  123.             }  
  124.             return query;  
  125.         }  
  126.          
  127.         /**
  128.          * @param fieldName
  129.          * @param value
  130.          * @return
  131.          * @Author: lulei   
  132.          * @Description: StringField属性的搜索
  133.          */  
  134.         public Query getStringFieldQuery(String value, String fieldName){  
  135.             Query query = null;  
  136.             query = new TermQuery(new Term(fieldName, value));  
  137.             return query;  
  138.         }  
  139.          
  140.         /**
  141.          * @param fields
  142.          * @param values
  143.          * @return
  144.          * @Author: lulei   
  145.          * @Description: 多个StringField属性的搜索
  146.          */  
  147.         public Query getStringFieldQuery(String[] values, String[] fields, Occur occur){  
  148.             if (fields == null || values == null || fields.length != values.length){  
  149.                 return null;  
  150.             }  
  151.             ArrayList<Query> querys = new ArrayList<Query>();  
  152.             ArrayList<Occur> occurs = new ArrayList<Occur>();  
  153.             for (int i = 0; i < fields.length; i++){  
  154.                 querys.add(getStringFieldQuery(values[i], fields[i]));  
  155.                 occurs.add(occur);  
  156.             }  
  157.             return getBooleanQuery(querys, occurs);  
  158.         }  
  159.          
  160.         /**
  161.          * @param key
  162.          * @param field
  163.          * @param lucene43
  164.          * @return
  165.          * @throws ParseException
  166.          * @Author: lulei   
  167.          * @Description: 查询字符串和单个查询域 QueryParser是否使用4.3
  168.          */  
  169.         public Query getOneFieldQuery(String key, String field, boolean lucene43) throws ParseException{  
  170.             if (key == null || key.length() < 1){  
  171.                 return null;  
  172.             }  
  173.             if (lucene43){  
  174.                 return getOneFieldQuery(key, field);  
  175.             }  
  176.             @SuppressWarnings("deprecation")  
  177.             QueryParser parse = new QueryParser(Version.LUCENE_30, field, analyzer);  
  178.             Query query = null;  
  179.             query = parse.parse(key);  
  180.             return query;  
  181.         }  
  182.          
  183.         /**
  184.          * @param key
  185.          * @param field
  186.          * @Author: lulei   
  187.          * @Description: key开头的查询字符串,和单个域匹配
  188.          */  
  189.         public Query getStartQuery(String key, String field) {  
  190.             if (key == null || key.length() < 1){  
  191.                 return null;  
  192.             }  
  193.             Query query = new PrefixQuery(new Term(field, key));  
  194.             return  query;  
  195.         }  
  196.          
  197.         /**
  198.          * @param key
  199.          * @param fields
  200.          * @param occur
  201.          * @Author: lulei   
  202.          * @Description: key开头的查询字符串,和多个域匹配,每个域之间的关系由occur确定
  203.          */  
  204.         public Query getStartQuery(String key, String []fields, Occur occur){  
  205.             if (key == null || key.length() < 1){  
  206.                 return null;  
  207.             }  
  208.             ArrayList<Query> querys = new ArrayList<Query>();  
  209.             ArrayList<Occur> occurs = new ArrayList<Occur>();   
  210.             for (String field : fields) {  
  211.                 querys.add(getStartQuery(key, field));  
  212.                 occurs.add(occur);  
  213.             }  
  214.             return getBooleanQuery(querys, occurs);  
  215.         }  
  216.          
  217.         /**
  218.          * @param key
  219.          * @param fields
  220.          * @Author: lulei   
  221.          * @Description: key开头的查询字符串,和多个域匹配,每个域之间的关系Occur.SHOULD
  222.          */  
  223.         public Query getStartQuery(String key, String []fields) {  
  224.             return getStartQuery(key, fields, Occur.SHOULD);  
  225.         }  
  226.          
  227.         /**
  228.          * @param key
  229.          * @param field
  230.          * @param slop
  231.          * @return
  232.          * @Author:lulei   
  233.          * @Description: 自定每个词元之间的最大距离
  234.          */  
  235.         public Query getPhraseQuery(String key, String field, int slop) {  
  236.             if (key == null || key.length() < 1){  
  237.                 return null;  
  238.             }  
  239.             StringReader reader = new StringReader(key);  
  240.             PhraseQuery query = new PhraseQuery();  
  241.             query.setSlop(slop);  
  242.             try {  
  243.                 TokenStream  tokenStream  = this.analyzer.tokenStream(field, reader);  
  244.                 tokenStream.reset();  
  245.                 CharTermAttribute  term = tokenStream.getAttribute(CharTermAttribute.class);  
  246.                 while(tokenStream.incrementToken()){   
  247.                     query.add(new Term(field, term.toString()));  
  248.                 }   
  249.                 reader.close();   
  250.             } catch (IOException e) {  
  251.                 e.printStackTrace();  
  252.                 return null;  
  253.             }  
  254.             return query;  
  255.         }  
  256.          
  257.         /**
  258.          * @param key
  259.          * @param fields
  260.          * @param slop
  261.          * @param occur
  262.          * @return
  263.          * @Author:lulei   
  264.          * @Description: 自定每个词元之间的最大距离,查询多个域,每个域之间的关系由occur确定
  265.          */  
  266.         public Query getPhraseQuery(String key, String[] fields, int slop, Occur occur) {  
  267.             if (key == null || key.length() < 1){  
  268.                 return null;  
  269.             }  
  270.             ArrayList<Query> querys = new ArrayList<Query>();  
  271.             ArrayList<Occur> occurs = new ArrayList<Occur>();   
  272.             for (String field : fields) {  
  273.                 querys.add(getPhraseQuery(key, field, slop));  
  274.                 occurs.add(occur);  
  275.             }  
  276.             return getBooleanQuery(querys, occurs);  
  277.         }  
  278.          
  279.         /**
  280.          * @param key
  281.          * @param fields
  282.          * @param slop
  283.          * @return
  284.          * @Author:lulei   
  285.          * @Description:  自定每个词元之间的最大距离,查询多个域,每个域之间的关系是Occur.SHOULD
  286.          */  
  287.         public Query getPhraseQuery(String key, String[] fields, int slop) {  
  288.             return getPhraseQuery(key, fields, slop, Occur.SHOULD);  
  289.         }  
  290.          
  291.         /**
  292.          * @param key
  293.          * @param field
  294.          * @return
  295.          * @Author:lulei   
  296.          * @Description: 通配符检索 eg:getWildcardQuery("a*thor", "field")
  297.          */  
  298.         public Query getWildcardQuery(String key, String field) {  
  299.             if (key == null || key.length() < 1){  
  300.                 return null;  
  301.             }  
  302.             return new WildcardQuery(new Term(field, key));  
  303.         }  
  304.          
  305.         /**
  306.          * @param key
  307.          * @param fields
  308.          * @param occur
  309.          * @return
  310.          * @Author:lulei   
  311.          * @Description: 通配符检索,域之间的关系为occur
  312.          */  
  313.         public Query getWildcardQuery(String key, String[] fields, Occur occur) {  
  314.             if (key == null || key.length() < 1){  
  315.                 return null;  
  316.             }  
  317.             ArrayList<Query> querys = new ArrayList<Query>();  
  318.             ArrayList<Occur> occurs = new ArrayList<Occur>();   
  319.             for (String field : fields) {  
  320.                 querys.add(getWildcardQuery(key, field));  
  321.                 occurs.add(occur);  
  322.             }  
  323.             return getBooleanQuery(querys, occurs);  
  324.         }  
  325.          
  326.         /**
  327.          * @param key
  328.          * @param fields
  329.          * @return
  330.          * @Author:lulei   
  331.          * @Description: 通配符检索,域之间的关系为Occur.SHOULD
  332.          */  
  333.         public Query getWildcardQuery(String key, String[] fields) {  
  334.             return getWildcardQuery(key, fields, Occur.SHOULD);  
  335.         }  
  336.          
  337.         /**
  338.          * @param keyStart
  339.          * @param keyEnd
  340.          * @param field
  341.          * @param includeStart
  342.          * @param includeEnd
  343.          * @return
  344.          * @Author:lulei   
  345.          * @Description: 范围搜索
  346.          */  
  347.         public Query getRangeQuery (String keyStart, String keyEnd, String field, boolean includeStart, boolean includeEnd) {  
  348.             return TermRangeQuery.newStringRange(field, keyStart, keyEnd, includeStart, includeEnd);  
  349.         }  
  350.          
  351.         /**
  352.          * @param min
  353.          * @param max
  354.          * @param field
  355.          * @param includeMin
  356.          * @param includeMax
  357.          * @return
  358.          * @Author:lulei   
  359.          * @Description: 范围搜索
  360.          */  
  361.         public Query getRangeQuery (int min, int max, String field, boolean includeMin, boolean includeMax) {  
  362.             return NumericRangeQuery.newIntRange(field, min, max, includeMin, includeMax);  
  363.         }  
  364.          
  365.         /**
  366.          * @param min
  367.          * @param max
  368.          * @param field
  369.          * @param includeMin
  370.          * @param includeMax
  371.          * @return
  372.          * @Author:lulei   
  373.          * @Description: 范围搜索
  374.          */  
  375.         public Query getRangeQuery (float min, float max, String field, boolean includeMin, boolean includeMax) {  
  376.             return NumericRangeQuery.newFloatRange(field, min, max, includeMin, includeMax);  
  377.         }  
  378.          
  379.         /**
  380.          * @param min
  381.          * @param max
  382.          * @param field
  383.          * @param includeMin
  384.          * @param includeMax
  385.          * @return
  386.          * @Author:lulei   
  387.          * @Description: 范围搜索
  388.          */  
  389.         public Query getRangeQuery (double min, double max, String field, boolean includeMin, boolean includeMax) {  
  390.             return NumericRangeQuery.newDoubleRange(field, min, max, includeMin, includeMax);  
  391.         }  
  392.          
  393.         public static void main(String[] args) throws IOException {  
  394.         }  
  395.     }  
复制代码

      PackQuery类的构造方法,可以手动指定分词器也可以使用索引的分词器。个人建议,在项目中使用索引中的分词器,这样就不会因为分词器的不同造成不知名的错误。

相关内容:
基于lucene的案例开发1:lucene初始认知

基于lucene的案例开发2:索引数学模型

基于lucene的案例开发3:索引文件结构

基于lucene的案例开发4:创建索引

基于lucene的案例开发5:搜索索引

基于lucene的案例开发6:分词器介绍

基于lucene的案例开发7:Query查询

基于lucene的案例开发8:IndexSearcher中检索方法

基于lucene的案例开发9:案例初识

基于lucene的案例开发10:搜索后台基础,JsonUtil & XmlUtil类介绍

基于lucene的案例开发11:项目常用类ClassUtil & CharsetUtil介绍

基于lucene的案例开发12:数据库连接池

基于lucene的案例开发13:实现实时索引基本原理

基于lucene的案例开发14:实时索引管理类IndexManager

基于lucene的案例开发15:实时索引的检索

基于lucene的案例开发16:实时索引的修改

基于lucene的案例开发17:查询语句创建PackQuery

基于lucene的案例开发18:纵横小说更新列表页抓取

基于lucene的案例开发19:纵横小说简介页采集

基于lucene的案例开发20:纵横小说章节列表采集

基于lucene的案例开发21:纵横小说阅读页采集

资料来源:
http://blog.csdn.net/xiaojimanman/article/details/44656141



欢迎加入about云群371358502、39327136,云计算爱好者群,亦可关注about云腾讯认证空间||关注本站微信

已有(1)人评论

跳转到指定楼层
LeucotheaShi 发表于 2015-4-15 14:21:44
赞~谢谢楼主分享~~~~~~
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条