文档章节

lucene学习6-各种查询

明舞
 明舞
发布于 2014/11/18 23:48
字数 1798
阅读 37
收藏 1
点赞 0
评论 1

目前缺了数值和日期的模糊查询与精确查询,等学会了以后再更新


package com.test;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

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.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.xml.builders.NumericRangeFilterBuilder;
import org.apache.lucene.queryparser.xml.builders.NumericRangeQueryBuilder;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TermRangeQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.WildcardQuery;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.Version;

public class SearcherUtil {
	private  Directory directory;
	private IndexReader reader;
	private Date[] dates = null;
	private String[] ids = {"1","2","3","4","5","6"}; 
    private String[] emails = {"aa@tom.com","bb@edu.com","cc@sina.com","dd@yaho.com","ee@qq.com","ff@163.com"};
    private String[] content = {"welcome to 1 room,I like tom","welcome to 2 room","welcome to 3 room","welcome to 4 room,i like qq","welcome to 5 room","welcome to 6 room",};
    private int[]    attachs = {1,4,3,2,5,1}; //模拟附件数量  ,专门用来演示为数字加索引
    private String[] names = {"张三","李四","王五","马六","赵七","刘八"};
    private Map<String, Float>  scorsMap = new  HashMap<String, Float>();


	public SearcherUtil() throws Exception {
		directory = new RAMDirectory();
		index();
	}

	//或者查询器
	public IndexSearcher getSearcher() throws Exception {
		if (reader == null) {
			reader = DirectoryReader.open(directory);
		} else {
			IndexReader tr = DirectoryReader
					.openIfChanged((DirectoryReader) reader);
			if (tr != null) {// 如果已经做了改变,并且返回了全新的reader
				reader.close();	
				reader = tr;
			}
		}
		return new IndexSearcher(reader);
	}
	//字符精确查询
	public void  searchByTerm(String field,String name,int num) throws Exception { //在这里的term为精确查找,稍微有一点不同都无法匹配,这里的匹配是以字段为单位的,比如tom一个单词可以匹配,但是t一个字母无法匹配
		IndexSearcher searcher = getSearcher();
		Query query = new TermQuery(new Term(field,name));
		TopDocs tds = searcher.search(query,num);
	    System.out.println("一共查询了:"+tds.totalHits);
	    for ( ScoreDoc sd : tds.scoreDocs) {
	    	Document doc = searcher.doc(sd.doc);
	    	System.out.println(doc.get("id")+"id<------->"+doc.get("name")+"<------name"+doc.get("email")+"email<-----");
		}
	    
	}
	
	//字符范围查询
	public void searchByTermRange(String field,String start,String end,int num	)throws Exception{
		IndexSearcher searcher =getSearcher();
		Query query =  new TermRangeQuery(field, new BytesRef(start), new BytesRef(end), true, true);
		TopDocs tds = searcher.search(query,num);
	    System.out.println("一共查询了:"+tds.totalHits);
	    for ( ScoreDoc sd : tds.scoreDocs) {
	    	Document doc = searcher.doc(sd.doc);
	    	System.out.println(doc.get("id")+"id<------->"+doc.get("name")+"<------name"+doc.get("email")+"email<-----");
		}
		
	}
	
	
	
	
	//按前缀查询
	public void searchByPrefix(String field,String value,int num)throws Exception{
		IndexSearcher searcher =getSearcher();
		Query query =  new PrefixQuery(new Term(field,value));
		TopDocs tds = searcher.search(query,num);
	    System.out.println("一共查询了:"+tds.totalHits);
	    for ( ScoreDoc sd : tds.scoreDocs) {
	    	Document doc = searcher.doc(sd.doc);
	    	System.out.println(doc.get("id")+"id<------->"+doc.get("name")+"<------name"+doc.get("email")+"email<-----");
		}
		
	}
	
	
	//通配符查询
	public void searchByWildcard(String field,String value,int num)throws Exception{
		IndexSearcher searcher =getSearcher();
		Query query =  new WildcardQuery(new Term(field,value));
		TopDocs tds = searcher.search(query,num);
	    System.out.println("一共查询了:"+tds.totalHits);
	    for ( ScoreDoc sd : tds.scoreDocs) {
	    	Document doc = searcher.doc(sd.doc);
	    	System.out.println(doc.get("id")+"id<------->"+doc.get("name")+"<------name"+doc.get("email")+"email<-----");
		}
		
	}
	
	
	//模糊查询    会有距离限制,一般情况下就算有一些字符不同,也可以查询出来
	public void searchByFuzzy(int num)throws Exception{
		IndexSearcher searcher =getSearcher();
		FuzzyQuery query =  new FuzzyQuery(new Term("email","aatom.com")); //在构造函数时可以传入值设定匹配相似度,距离等
		System.out.println("query.getPrefixLength()"+query.getPrefixLength());
		TopDocs tds = searcher.search(query,num);
	    System.out.println("一共查询了:"+tds.totalHits);
	    for ( ScoreDoc sd : tds.scoreDocs) {
	    	Document doc = searcher.doc(sd.doc);
	    	System.out.println(doc.get("id")+"id<------->"+doc.get("name")+"<------name"+doc.get("email")+"email<-----");
		}
		
	}
	
	//boolean查询
	public void searchByBoolean(int num)throws Exception{
		IndexSearcher searcher =getSearcher();
		BooleanQuery query =  new BooleanQuery();
		query.add(new TermQuery(new Term("email","aa@tom.com")),Occur.MUST);//,Occur.MUST的意思是email必须是这个值,必须符合这个条件   Occur.SHOULD类似于可以符合,也可以不符合,Occur.MUST_NOT 不能出现
		query.add(new TermQuery(new Term("content","like")),Occur.SHOULD);  //可以叠加多条的,后面的条件类似于与或非门.sql的or 和  and
		TopDocs tds = searcher.search(query,num);
	    System.out.println("一共查询了:"+tds.totalHits);
	    for ( ScoreDoc sd : tds.scoreDocs) {
	    	Document doc = searcher.doc(sd.doc);
	    	System.out.println(doc.get("id")+"id<------->"+doc.get("name")+"<------name"+doc.get("email")+"email<-----");
		}
		
	}
	
	
	//Phrase查询   短语查询
	public void searchByPhrase	(int num)throws Exception{
		IndexSearcher searcher =getSearcher();
		PhraseQuery query =  new PhraseQuery();
		query.setSlop(1);
		//第一个term
		query.add(new Term("content","i"));
		//产生距离之后的第二个term   如果两个调换了顺序就不可以查询到了。  整个查询的意思是,查询在i之后有一个like 的短语的记录
		query.add(new Term("content","like"));
		TopDocs tds = searcher.search(query,num);
	    System.out.println("一共查询了:"+tds.totalHits);
	    for ( ScoreDoc sd : tds.scoreDocs) {
	    	Document doc = searcher.doc(sd.doc);
	    	System.out.println(doc.get("id")+"id<------->"+doc.get("name")+"<------name"+doc.get("email")+"email<-----");
		}
		
	}
	
	//建立索引
	 public void index() throws Exception {
	    	IndexWriter writer = null;
	    	writer = new IndexWriter(directory, new IndexWriterConfig(Version.LATEST, new StandardAnalyzer(Version.LATEST)));
	    	writer.deleteAll();
	    	Document doc = null;
	    	for (int i = 0; i < ids.length; i++) {
	    		doc = new Document();
				doc.add(new Field("id", ids[i],Field.Store.YES,Field.Index.NOT_ANALYZED));
				//field.Store.YES的意思是,是不是把该域中的内容完全存储到索引文件当中,方便进行文本的还原。
				//field.Store.NO的意思是,把这个域的内容不存储到索引文件中,但是呢,可以被索引。此时内容无法完全还原。就是无法使用doc.get来还原。一般的搜索引擎也是只显示简介,不会显示所有内容
			    //---------------------------------
				//Field.Index叫做索引选项。  
				//Index.ANALYZED  进行分词和索引,适用于标题和内容
				//Index.NOT_ANALYZED 进行索引,但是不尽兴分词,如身份证号,姓名,ID等,适用于精确搜索
				//Index.ANALYZED_NOT_NORMS 进行分词,但是不存储norms信息,这个norms中包括了创建索引的时间和权值等信息。
				//Index.NOT_ANALYZED_NOT_NORMS 既不进行分词也不存储norms。
				//Index.NO 不进行索引
				Field contentField = new Field("content", content[i],Field.Store.NO,Field.Index.ANALYZED);

				
				Field emailField  = new Field("email", emails[i],Field.Store.YES,Field.Index.NOT_ANALYZED); 
				doc.add(emailField);
				doc.add(contentField);
	    	    doc.add(new Field("name", names[i],Field.Store.YES,Field.Index.NOT_ANALYZED_NO_NORMS));
	    	    doc.add(new IntField("attachs", attachs[i], Field.Store.YES));
	    	    String et = emails[i].substring(emails[i].lastIndexOf("@")+1);
	    	    if (scorsMap.containsKey(et)) {
	    	    	 //为索引域添加权,例如,这里的例子是,如果这个email域有包含@tom.com的就设置content域的权值为2.0,如果为@yaho.com的就设置content域的权值为2.5,其他的设置为0.5,默认值是1.0
	    	        //3.5版本有个为document文档添加权的,但是现在4.0以上版本已经没有了,目前所知是可以为field添加权值,请注意每个域的区别
	    	    	contentField.setBoost(scorsMap.get(et));
				}
	    	    else {
	    	    	contentField.setBoost(0.5f);
				}
	    	    
	    	    writer.addDocument(doc);
	    	}

	    	if (writer!=null) {  //如果不尽兴close操作,或者commit操作,那么索引不起效,会报出索引找不到的异常
				writer.close();
			}
		}

}
package com.junittest;

import org.junit.Before;
import org.junit.Test;

import com.test.IndexUtil;
import com.test.SearcherUtil;

public class testSearch {
     private SearcherUtil su ;
	@Before //索引方法
	public void init() throws Exception {
		su = new SearcherUtil();
	}
	
	
	@Test //精确查询
	public void searchByTerm() throws Exception {
		su.searchByTerm("content", "i", 3); //中文都无法查询出来,估计是使用的分词器的原因,得用中文的分词器
		
	}
	@Test  //范围查询
	public void searchByTermRange() throws Exception {
		su.searchByTermRange("email", "a", "b",10);//这句的意思是:从email这个field中,查询,从以a开头的值开始,一直查到包含b的那条数据结尾,一共查10条
		System.out.println("------------------");
		su.searchByTermRange("name", "a", "c",10);//数字类型无法使用该查询查询出来,
		System.out.println("------------------");
		su.searchByTermRange("attachs", "1", "3",10);
		
	}
	
	@Test  //前缀查询
	public void searchByPrefix() throws Exception {
		su.searchByPrefix("email", "a",10);//这句的意思是:从email这个field中,查询,从以a开头的记录,一共查10条
		
		
	}
	
	@Test  //通配符查询
	public void searchByWildcard() throws Exception {
		//*表示多个字符  ?表示一个字符
		su.searchByWildcard("email", "a*",10);//这句的意思是:从email这个field中,查询包含有匹配a+通配符的 记录,一共查10条
		
		
	}
	
	@Test  //boolean查询
	public void searchByBoolean() throws Exception {
		//*表示多个字符  ?表示一个字符
		su.searchByBoolean(10);//这句的意思是:从email这个field中,查询包含有匹配a+通配符的 记录,一共查10条
		
		
	}
	
	@Test  //phrase查询  短语查询
	public void searchByPhrase() throws Exception {
		//*表示多个字符  ?表示一个字符
		su.searchByPhrase(10);//这句的意思是:从email这个field中,查询包含有匹配a+通配符的 记录,一共查10条
		
		
	}
	
	@Test  //模糊查询  短语查询
	public void searchByFuzzy() throws Exception { 
		//*表示多个字符  ?表示一个字符
		su.searchByFuzzy(10);//这句的意思是:从email这个field中,查询包含有匹配a+通配符的 记录,一共查10条
		
		
	}
}


© 著作权归作者所有

共有 人打赏支持
明舞
粉丝 227
博文 424
码字总数 516555
作品 0
程序员
加载中

评论(1)

明舞
明舞
我擦,我怎么没有把主类代码给放上来,我个傻缺,晚上放
这么说吧,Lucene很简单,其实就是个框架,用于全文检索用的

我是风月连城,喜欢用简单的语言阐述知识点 长期分享原创java文章,分享进阶架构师学习笔记及学习资料 喜欢的大屌们可以关注下,共同学习,一起进步 ps:由于工资迟迟不发,影响心情,好几天没写文章...

java进阶架构师
2017/09/28
0
0
Apache Lucene-使用简单介绍

首先呢,学习任何一门新的亦或是旧的开源技术,百度其中一二是最简单的办法,先了解其中的大概,思想等等。这里就贡献一个讲解很到位的ppt。已经被我转成了PDF,便于搜藏。   其次,关于第...

LANTIANFEIYING
2016/10/19
0
0
Lucene-5.2.1学习:入门

1、Lucene的核心jar包 lucene-core-5.2.1.jar lucene-analyzers-common-5.2.1.jar lucene-queryparser-5.2.1.jar 2、主要开发包说明 org.apache.lucene.analysis:语言分析器,主要用于分词 ......

Harmel
2015/08/11
9.2K
3
Lucene知识小总结6:搜索

建好索引之后必定是进行搜索的节奏了,lucene关于搜索这部分内容是包含很多知识的,这里只是一个梗概,因为作为知识点的小梳理,没有探讨高级的知识点,都是先对知识有个小印象,之后慢慢学习...

heroShane
2014/02/23
0
0
Apache Lucene 6.2.1 中文文档-首页

原文链接:CDCN-码上中国 Lucene 是一个基于Java的全文搜索引擎。Lucene不是要给完整的应用程序,而是 一个可以轻松地向应用程序添加搜索功能的代码库API接口。 这是Apache Lucene 6.2.1的官...

码上中国博客
2016/11/05
164
0
Lucene搜索流程(4.Query)

最进由于工作的事和国庆,回家了没有环境来写文章,所以搁置了好久,人一懒就不想动,其中有人催我,想想也不能半途而废了,由于之前也写了些草稿,决心今天一定要写了这玩意。闲话不多说,开...

曾杰
2012/10/10
0
2
《深入理解Elasticsearch(原书第2版)》——第1章  Elasticsearch简介

第1章 Elasticsearch简介 摘要: 欢迎来到Elasticsearch的世界并阅读本书第2版。通过阅读本书,我们将带领你接触与Elasticsearch紧密相关的各种话题。请注意,本书不是为初学者写的。笔者将本...

哲别0
2017/11/01
0
0
历时一年,我的著作《从Lucene到Elasticsearch》已出版!

一、前言 决定在CSDN写博客的原因是想把自己解决过的问题、踩过的坑、总结出来的经验记录下来,作为编程之路的“笔记本”,同时也能给遇到同样问题的人提供参考、节省时间,写书的初衷也一样...

napoay
2017/12/05
0
0
Apache Lucene 5.4.0 发布,Java 搜索引擎

Apache Lucene™ 5.4.0 发布,此版本包括大量的 bug 修复,优化和改进,现已提供下载: src="http://lucene.apache.org/core/mirrors-core-latest-redir.html" href="http://lucene.apache.......

oschina
2015/12/15
2.5K
8
Lucene教程详解

注明:本文是由本人在开发有关基于lucene资源检索系统时的一点总结,其中一部分是自己根据开发过程自己总结的,也有部分是摘自网络,因无法获取当时摘文的地址,所以在此没有写源地址。 转载...

长平狐
2012/11/12
1K
2

没有更多内容

加载失败,请刷新页面

加载更多

下一页

idea tomcat 远程调试

tomcat 配置 编辑文件${tomcat_home}/bin/catalina.sh,在文件开头添加如下代码。    CATALINA_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=7829" Idea端配......

qwfys
今天
1
0
遍历目录下的文件每250M打包一个文件

#!/usr/bin/env python # -*- utf-8 -*- # @Time : 2018/7/20 0020 下午 10:16 # @Author : 陈元 # @Email : abcmeabc@163.com # @file : tarFile.py import os import tarfile import thr......

寻爱的小草
今天
1
0
expect同步文件&expect指定host和要同步的文件&构建文件分发系统&批量远程执行命令

20.31 expect脚本同步文件 expect通过与rsync结合,可以在一台机器上把文件自动同步到多台机器上 编写脚本 [root@linux-5 ~]# cd /usr/local/sbin[root@linux-5 sbin]# vim 4.expect#!/...

影夜Linux
今天
1
0
SpringBoot | 第九章:Mybatis-plus的集成和使用

前言 本章节开始介绍数据访问方面的相关知识点。对于后端开发者而言,和数据库打交道是每天都在进行的,所以一个好用的ORM框架是很有必要的。目前,绝大部分公司都选择MyBatis框架作为底层数...

oKong
今天
12
0
win10 上安装解压版mysql

1.效果 2. 下载MySQL 压缩版 下载地址: https://downloads.mysql.com/archives/community/ 3. 配置 3.1 将下载的文件解压到合适的位置 我最终将myql文件 放在:D:\develop\mysql 最终放的位...

Lucky_Me
今天
2
0
linux服务器修改mtu值优化cpu

一、jumbo frames 相关 1、什么是jumbo frames Jumbo frames 是指比标准Ethernet Frames长的frame,即比1518/1522 bit大的frames,Jumbo frame的大小是每个设备厂商规定的,不属于IEEE标准;...

问题终结者
今天
2
0
expect脚本同步文件expect脚本指定host和要同步的文件 构建文件分发系统批量远程执行命令

expect脚本同步文件 在一台机器上把文件同步到多台机器上 自动同步文件 vim 4.expect [root@yong-01 sbin]# vim 4.expect#!/usr/bin/expectset passwd "20655739"spawn rsync -av ro...

lyy549745
今天
1
0
36.rsync下 日志 screen

10.32/10.33 rsync通过服务同步 10.34 linux系统日志 10.35 screen工具 10.32/10.33 rsync通过服务同步: rsync还可以通过服务的方式同步。那需要开启一个服务,他的架构是cs架构,客户端服务...

王鑫linux
今天
1
0
matplotlib 保存图片时的参数

简单绘图 import matplotlib.pyplot as pltplt.plot(range(10)) 保存为csv格式,放大后依然很清晰 plt.savefig('t1.svg') 普通保存放大后会有点模糊文件大小20多k plt.savefig('t5.p...

阿豪boy
今天
3
0
java 8 复合Lambda 表达式

comparator 比较器复合 //排序Comparator.comparing(Apple::getWeight);List<Apple> list = Stream.of(new Apple(1, "a"), new Apple(2, "b"), new Apple(3, "c")) .collect(......

Canaan_
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部