lucene全文检索多种查询检索简单案例

针对lucene全文检索引擎写一下多种查询检索的方式

这里采用的是英文分词,单独写了一篇关于中文分词与高亮显示,如下:
lucene全文检索之 中文分词 以及 高亮显示,点击进入

另外分享一个 lucene索引库查看器 ,点击进入

lucene官网 http://lucene.apache.org这里写链接内容

首先需要引入lucene的maven依赖,如下:

<dependency><groupId>org.apache.lucenegroupId><artifactId>lucene-coreartifactId><version>5.3.1version>
dependency><dependency><groupId>org.apache.lucenegroupId><artifactId>lucene-queryparserartifactId><version>5.3.1version>
dependency><dependency><groupId>org.apache.lucenegroupId><artifactId>lucene-analyzers-commonartifactId><version>5.3.1version>
dependency>

下面我就直接贴代码吧,如下:

package luceneDemo;import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.IntField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
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.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.search.TermRangeQuery;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;/*** 全文检索案例* @author mszhou*/
public class luceneDemo {/*** 演示将数据写入索引文件中* 在项目中我们会定时将数据写入索引文件中,* 然后在索引文件中进行搜索,这样比在数据库中搜索效率高的多,* 而且检索远比数据库的模糊匹配强大的多,这也是检索工具牛逼之处* * 需要注意的是,如果在项目中定时写入索引,* 需要判断下该数据是否存在,存在则修改,不存在再进行新增* * @param luceneDir 该参数表示索引所存放的目录*/public static void writeIndex(String luceneDir){IndexWriter writer = null;//声明创建索引写入器 try{//创建索引目录 , 这里参数luceneDir 表示索引存放目录Directory dir=FSDirectory.open(Paths.get(luceneDir));//创建标准分词器(一般英文使用这个,不适合中文使用)Analyzer analyzer=new StandardAnalyzer(); // 标准分词器IndexWriterConfig iwc=new IndexWriterConfig(analyzer);//创建索引写入器实例,通过IndexWriterConfig设置相关配置writer=new IndexWriter(dir, iwc);//=== 这里造一些数据用作演示,也可以直接读取数据库中的数据 开始========List > list=new ArrayList>();//假数据1 Map map1 =new HashMap();map1.put("title", "weejij dasa ");//表示标题字段map1.put("centent", "hdaiads sd s g r44e r hgg f hd 4 ");//表示标题字段list.add(map1);//假数据2 Map map2 =new HashMap();map2.put("title", "demo12 i33s ss");//表示标题字段map2.put("centent", "hdaiads sd s g r44e r hgg f hd 4 ");//表示标题字段   list.add(map2);//假数据1 Map map3 =new HashMap();map3.put("title", "demo 12i131s ss");//表示标题字段map3.put("centent", "hdaiads sd s g r44e r hgg f hd 4 ");//表示标题字段   list.add(map3);//=== 这里造一些数据用作演示,也可以直接读取数据库中的数据 结束========//遍历数据,并且将数据写入到索引中for(int i=0 ;i// ======   获取数据开始 ====== Map mapCen=list.get(i);String title =  mapCen.get("title").toString();//获取标题String centent = mapCen.get("centent").toString();//获取内容// ======   获取数据结束 ====== //========= 将数据写入索引开始  =================//创建Document对象,Document表示lucene索引的数据结构单元Document doc=new Document();//添加id 数据,最后面Field.Store.YES表示存储该字段doc.add(new IntField("id", i,  Field.Store.YES));/*添加标题数据,最后面Field.Store.YES 表示存储该字段*注意:如果需要检索该字段,建议使用TextField类型,并且设置为 Field.Store.YES*/doc.add(new TextField("title",title , Field.Store.YES));//添加标题内容数据,最后面Field.Store.NO  表示不存储该字段doc.add(new TextField("centent", centent, Field.Store.NO));// 写入索引writer.addDocument(doc); //========= 将数据写入索引结束  =================}}catch(Exception e){System.out.println("发生了异常!");e.printStackTrace();}finally{try {writer.close();//关闭流,一定要记得关闭} catch (IOException e) {}}}/*** 演示对特定项搜索* @param luceneDir 该参数表示索引所存放的目录* @param field 表示需要搜索的项(就是写入时属性字段名称)* @param qu 需要检索的关键词*/public static void testTermQuery(String luceneDir,String field, String qu){IndexReader reader = null;//声明索引读取器try{//创建索引目录 , 这里参数luceneDir 表示索引存放目录Directory dir=FSDirectory.open(Paths.get(luceneDir));//创建索引读取器reader=DirectoryReader.open(dir);//创建索引搜索器IndexSearcher is=new IndexSearcher(reader);//创建查询器,参数field表示属性字段,qu表示检索的关键词Term t=new Term(field,qu);Query query=new TermQuery(t);//这里查询前10条匹配的数据,第二个参数为10表示查前十条TopDocs hits=is.search(query, 10);//打印System.out.println("检索文档字段"+ field +" ,匹配 "+qu+" , 查询到"+hits.totalHits+"个记录");//遍历查询到的数据for(ScoreDoc scoreDoc:hits.scoreDocs){Document doc=is.doc(scoreDoc.doc);String id  = doc.get("id")==null?"":doc.get("id").toString();//获取idString title  = doc.get("title")==null?"":doc.get("title").toString();//获取标题//由于写入的时候 ,设置了Field.Store.NO 表示不存储该字段,所以这里读取不到//String centent  = doc.get("centent")==null"":doc.toString();//获取内容//打印数据System.out.println("id是:"+id+" ,标题是:"+title);}}catch(Exception e){System.out.println("发生了异常!");e.printStackTrace();}finally{try {reader.close();//关闭流,一定要记得关闭} catch (IOException e) {}}}/*** 演示解析查询表达式(这里演示查询title字段属性)* @param luceneDir 该参数表示索引所存放的目录* @param titleStr 需要检索的关键词*/public static void testQueryParser(String luceneDir,String titleStr){IndexReader reader = null;//声明索引读取器try{//创建索引目录 , 这里参数luceneDir 表示索引存放目录Directory dir=FSDirectory.open(Paths.get(luceneDir));//创建索引读取器reader=DirectoryReader.open(dir);//创建索引搜索器IndexSearcher is=new IndexSearcher(reader);//创建标准分词器(一般英文使用这个,不适合中文使用)Analyzer analyzer=new StandardAnalyzer(); // 标准分词器//创建QueryParser查询器,查询title属性字段QueryParser parser=new QueryParser("title", analyzer);//设置查询关键词Query query=parser.parse(titleStr);//这里查询前10条匹配的数据,第二个参数为10表示查前十条TopDocs hits=is.search(query, 10);//打印信息System.out.println("匹配 "+titleStr+" , 查询到"+hits.totalHits+"个记录");//遍历查询到的数据for(ScoreDoc scoreDoc:hits.scoreDocs){Document doc=is.doc(scoreDoc.doc);String id  = doc.get("id")==null?"":doc.get("id").toString();//获取idString title  = doc.get("title")==null?"":doc.get("title").toString();//获取标题//由于写入的时候 ,设置了Field.Store.NO 表示不存储该字段,所以这里读取不到//String centent  = doc.get("centent").toString();//获取内容//打印数据System.out.println("id是:"+id+" ,标题是:"+title);}}catch(Exception e){System.out.println("发生了异常!");e.printStackTrace();}finally{try {reader.close();//关闭流,一定要记得关闭} catch (IOException e) {}}}/*** 演示指定项范围搜索* @param luceneDir 该参数表示索引所存放的目录*/public static void testTermRangeQuery(String luceneDir){IndexReader reader = null;//声明索引读取器try{//创建索引目录 , 这里参数luceneDir 表示索引存放目录Directory dir=FSDirectory.open(Paths.get(luceneDir));//创建索引读取器reader=DirectoryReader.open(dir);//创建索引搜索器IndexSearcher is=new IndexSearcher(reader);/** 创建TermRangeQuery查询器,查询title属性字段 从a到e范围内* 一般对于英文来说,进行ASC码范围查询还有那么一点意义,* 中文汉字进行ASC码值比较没什么太大意义,* 一般数字范围查询NumericRangeQuery用的比较多一点,* 比如价格,年龄,金额,数量等等都涉及到数字,数字范围查询需求也很普遍* * 后面两个boolean值用来控制是否包含两个上下边界值的。*/TermRangeQuery query=new TermRangeQuery("title", new BytesRef("a".getBytes()), new BytesRef("e".getBytes()), true, true);//这里查询前10条匹配的数据,第二个参数为10表示查前十条TopDocs hits=is.search(query, 10);//遍历查询到的数据for(ScoreDoc scoreDoc:hits.scoreDocs){Document doc=is.doc(scoreDoc.doc);String id  = doc.get("id")==null?"":doc.get("id").toString();//获取idString title  = doc.get("title")==null?"":doc.get("title").toString();//获取标题                //打印数据System.out.println("id是:"+id+" ,标题是:"+title);}}catch(Exception e){System.out.println("发生了异常!");e.printStackTrace();}finally{try {reader.close();//关闭流,一定要记得关闭} catch (IOException e) {}}       }/*** 演示指定数字范围* @param luceneDir  该参数表示索引所存放的目录*/public static void testNumericRangeQuery(String luceneDir){IndexReader reader = null;//声明索引读取器try{//创建索引目录 , 这里参数luceneDir 表示索引存放目录Directory dir=FSDirectory.open(Paths.get(luceneDir));//创建索引读取器reader=DirectoryReader.open(dir);//创建索引搜索器IndexSearcher is=new IndexSearcher(reader);/** 创建NumericRangeQuery查询器,查询id属性字段 从1到2范围内* * 后面两个boolean值用来控制是否包含两个上下边界值的。*/NumericRangeQuery query=NumericRangeQuery.newIntRange("id", 1, 2, true, true);//这里查询前10条匹配的数据,第二个参数为10表示查前十条TopDocs hits=is.search(query, 10);//遍历查询到的数据for(ScoreDoc scoreDoc:hits.scoreDocs){Document doc=is.doc(scoreDoc.doc);String id  = doc.get("id")==null?"":doc.get("id").toString();//获取idString title  = doc.get("title")==null?"":doc.get("title").toString();//获取标题                //打印数据System.out.println("id是:"+id+" ,标题是:"+title);}}catch(Exception e){System.out.println("发生了异常!");e.printStackTrace();}finally{try {reader.close();//关闭流,一定要记得关闭} catch (IOException e) {}}   }/*** 演示指定字符串开头搜索* @param luceneDir  该参数表示索引所存放的目录*/public static void testPrefixQuery(String luceneDir){IndexReader reader = null;//声明索引读取器try{//创建索引目录 , 这里参数luceneDir 表示索引存放目录Directory dir=FSDirectory.open(Paths.get(luceneDir));//创建索引读取器reader=DirectoryReader.open(dir);//创建索引搜索器IndexSearcher is=new IndexSearcher(reader);/** 创建NumericRangeQuery查询器,* 查询title属性字段分词索引以 w 开头的数据*/PrefixQuery query=new PrefixQuery(new Term("title","w"));//这里查询前10条匹配的数据,第二个参数为10表示查前十条TopDocs hits=is.search(query, 10);//遍历查询到的数据for(ScoreDoc scoreDoc:hits.scoreDocs){Document doc=is.doc(scoreDoc.doc);String id  = doc.get("id")==null?"":doc.get("id").toString();//获取idString title  = doc.get("title")==null?"":doc.get("title").toString();//获取标题                //打印数据System.out.println("id是:"+id+" ,标题是:"+title);}}catch(Exception e){System.out.println("发生了异常!");e.printStackTrace();}finally{try {reader.close();//关闭流,一定要记得关闭} catch (IOException e) {}}}/*** 演示多条件查询* @param luceneDir 该参数表示索引所存放的目录*/public static void testBooleanQuery(String luceneDir){IndexReader reader = null;//声明索引读取器try{//创建索引目录 , 这里参数luceneDir 表示索引存放目录Directory dir=FSDirectory.open(Paths.get(luceneDir));//创建索引读取器reader=DirectoryReader.open(dir);//创建索引搜索器IndexSearcher is=new IndexSearcher(reader);//========== 创建多个查询条件 开始===============BooleanQuery.Builder booleanQuery=new BooleanQuery.Builder();/** 条件1,* 创建NumericRangeQuery查询器,查询id属性字段 从1到2范围内* 后面两个boolean值用来控制是否包含两个上下边界值的。*/NumericRangeQuery query1=NumericRangeQuery.newIntRange("id", 1, 2, true, true);/** 添加查询条件1 到组合查询器中* BooleanClause.Occur.MUST 表示与 (相当于并且)* BooleanClause.Occur.SHOULD 表示或 (相当于或者)* BooleanClause.Occur.MUST_NOT 表示不包含 (相当于not)*/booleanQuery.add(query1,BooleanClause.Occur.MUST);/** 条件2, * 创建NumericRangeQuery查询器,* 查询title属性字段分词索引以 12 开头的数据*/PrefixQuery query2=new PrefixQuery(new Term("title","12"));/** 添加查询条件2 到组合查询器中* BooleanClause.Occur.MUST 表示与 (相当于并且)* BooleanClause.Occur.SHOULD 表示或 (相当于或者)* BooleanClause.Occur.MUST_NOT 表示不包含 (相当于not)*/booleanQuery.add(query2,BooleanClause.Occur.MUST);//========== 创建多个查询条件 结束===============/** 这里查询前10条匹配的数据,第二个参数为10表示查前十条* 这里查询检索表示满足条件1并且同时满足条件2的数据*/TopDocs hits=is.search(booleanQuery.build(), 10);//遍历查询到的数据for(ScoreDoc scoreDoc:hits.scoreDocs){Document doc=is.doc(scoreDoc.doc);String id  = doc.get("id")==null?"":doc.get("id").toString();//获取idString title  = doc.get("title")==null?"":doc.get("title").toString();//获取标题                //打印数据System.out.println("id是:"+id+" ,标题是:"+title);}}catch(Exception e){System.out.println("发生了异常!");e.printStackTrace();}finally{try {reader.close();//关闭流,一定要记得关闭} catch (IOException e) {}}}/*** 测试上面的方法* @param args* @throws Exception*/public static void main(String[] args) throws Exception {//表示索引目录String luceneDir =  "D://lucene";//测试该方法写入数据到索引文件中//writeIndex(luceneDir);//测试检索属性字段title,检索关键词为demo//testTermQuery(luceneDir,"title", "demo");//测试该方法检索询//testQueryParser(luceneDir,"demo");//测试指定项范围搜索方法//testTermRangeQuery(luceneDir);//测试指定数字范围搜索方法//testNumericRangeQuery(luceneDir);//测试指定字符串开头搜索方法//testPrefixQuery(luceneDir);//测试多条件查询搜索方法testBooleanQuery(luceneDir);}}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部