专栏首页eguid开源技术分享lucene全文搜索之四:创建索引搜索器、6种文档搜索器实现以及搜索结果分析(结合IKAnalyzer分词器的搜索器)基于lucene5.5.3

lucene全文搜索之四:创建索引搜索器、6种文档搜索器实现以及搜索结果分析(结合IKAnalyzer分词器的搜索器)基于lucene5.5.3

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/eguid_1/article/details/53088971

前言:

前面几章已经很详细的讲解了如何创建索引器对索引进行增删查(没有更新操作)、如何管理索引目录以及如何使用分词器,上一章讲解了如何生成索引字段和创建索引文档,并把创建的索引文档保存到索引目录,到这里我们已经知道如何建立索引,那么本章将会详解如何搜索索引目录中的索引文档索以及如何创建索引搜索器和六种文档搜索器(搜索器)的实现。

luncene5.5.3集合jar包下载地址:http://download.csdn.net/detail/eguid_1/9677589

一、创建索引搜索器

索引搜索器由索引目录创建,依赖搜索器进行全文搜索,部分搜索器依赖分词器进行分词查询

1、创建索引目录搜索器(即索引搜索器)

根据索引目录创建索引搜索(如果有多个索引目录,那么需要创建多个索引搜索,分别搜索出结果后再对搜索结果进行合并调整)

/**
	 * 创建索引搜索
	 * 
	 * @param indexReader -索引目录Reader
	 * @return
	 */
	public IndexSearcher createSearch(IndexReader indexReader) {
		IndexSearcher indexSearch = null;
		if (indexReader != null) {
			indexSearch = new IndexSearcher(indexReader);
		}
		return indexSearch;
	}
	/**
	 * 创建索引搜索
	 * @param dir -索引目录
	 * @return
	 */
	public IndexSearcher createSearch(Directory dir) {
		IndexSearcher indexSearch = null;
		try {
				IndexReader indexReader = DirectoryReader.open(dir);
				indexSearch = new IndexSearcher(indexReader);
		} catch (IOException e) {

		}
		return indexSearch;
	}

为了方便阅读,我们把六种搜索器放在最后, 这里先讲如何根据文档搜索器来搜索结果并且可以实现排序等等搜索结果的调整

2、搜索结果

/**
	 * 搜索
	 * 
	 * @param search
	 *            -索引搜索器
	 * @param query
	 *            -查询器
	 * @param num
	 *            -搜索结果数量
	 * @return
	 */
	public TopDocs search(IndexSearcher search, Query query, int num) {
		TopDocs topDocs = null;
		try {
			topDocs = search.search(query, num);
		} catch (IOException e) {

		}
		return topDocs;
	}

	/**
	 * 自定义排序搜索
	 * 
	 * @param search
	 *            -索引搜索
	 * @param query
	 *            -查询器
	 * @param num
	 *            -搜索结果数量
	 * @param sort
	 *            -排序
	 * @return
	 */
	public TopDocs search(IndexSearcher search, Query query, int num, Sort sort) {
		TopDocs topDocs = null;
		try {
			topDocs = search.search(query, num, sort);
		} catch (IOException e) {

		}
		return topDocs;
	}

	/**
	 * 搜索
	 * 
	 * @param search
	 *            -索引搜索器
	 * @param query
	 *            -查询器
	 * @param results
	 *            -搜索结果
	 */
	public void search(IndexSearcher search, Query query, Collector results) {
		try {
			if (query != null && results != null)
				search.search(query, results);
		} catch (IOException e) {

		}
	}

	/**
	 * 按照匹配分数搜索
	 * 
	 * @param search
	 * @param query
	 * @param after
	 *            -文档匹配分数
	 * @param numHits
	 *            -命中数量
	 * @return
	 */
	public TopDocs search(IndexSearcher search, Query query, ScoreDoc after, int numHits) {
		TopDocs topDocs = null;
		try {
			if (query != null && after != null)
				topDocs = search.searchAfter(after, query, numHits);
		} catch (IOException e) {

		}
		return topDocs;
	}

	/**
	 * 按照匹配分数搜索
	 * 
	 * @param search
	 * @param query
	 * @param after
	 *            -文档匹配分数
	 * @param numHits
	 *            -命中数量
	 * @param sort
	 *            自定义排序
	 * @return 搜索结果
	 */
	public TopDocs search(IndexSearcher search, Query query, ScoreDoc after, int numHits, Sort sort) {
		TopDocs topDocs = null;
		try {
			if (query != null && after != null && sort != null)
				topDocs = search.searchAfter(after, query, numHits, sort);
		} catch (IOException e) {

		}
		return topDocs;
	}

	/* 以下API已过时不建议再使用 */
	public TopDocs search(IndexSearcher search, Query query, Filter filter, int results) {
		TopDocs topDocs = null;
		try {
			topDocs = search.search(query, filter, results);
		} catch (IOException e) {

		}
		return topDocs;
	}

	public TopDocs search(IndexSearcher search, Query query, Filter filter, int results, Sort sort) {
		TopDocs topDocs = null;
		try {
			topDocs = search.search(query, filter, results, sort);
		} catch (IOException e) {

		}
		return topDocs;
	}

	public TopDocs search(IndexSearcher search, Query query, Filter filter, int results, Sort sort, boolean doDocScores,
			boolean doMaxScore) {
		TopDocs topDocs = null;
		try {
			topDocs = search.search(query, filter, results, sort, doDocScores, doMaxScore);
		} catch (IOException e) {

		}
		return topDocs;
	}

二、六种搜索器实现

/**
	 * 创建单词搜索器
	 * 
	 * @param fieldName
	 * @param key
	 * @return
	 */
	public Query createTermQuery(String fieldName, String key) {
		return new TermQuery(new Term(fieldName, key));
	}

	/**
	 * 创建前缀搜索器
	 * 
	 * @param fieldName
	 * @param key
	 * @return
	 */
	public Query createPrefixQeury(String fieldName, String key) {
		return new PrefixQuery(new Term(fieldName, key));
	}

	/**
	 * 创建范围搜索器
	 * 
	 * @param fieldName
	 * @param start
	 * @param end
	 * @return
	 */
	public Query createNumericRangeQuery(String fieldName, int start, int end) {
		return NumericRangeQuery.newIntRange(fieldName, start, end, true, true);
	}

	/**
	 * 根据分词器创建条件搜索
	 * 
	 * @param operator
	 * @param analyzer
	 * @param fieldName
	 * @param key
	 * @return
	 * @throws ParseException
	 */
	public Query createPhraseQueryByOperator(Operator operator, Analyzer analyzer, String fieldName, String key)
			throws ParseException {
		QueryParser qp = new QueryParser(fieldName, analyzer);
		if (operator != null) {
			qp.setDefaultOperator(operator);
		}
		return qp.parse(key);
	}

	/**
	 * 根据分词器创建模糊搜索
	 * 
	 * @param analyzer
	 * @param fieldName
	 * @param key
	 * @return
	 * @throws ParseException
	 */
	public Query createPhraseQuery(Analyzer analyzer, String fieldName, String key) throws ParseException {
		return createPhraseQueryByOperator(null, analyzer, fieldName, key);
	}

	/**
	 * 创建混合搜索器
	 * 
	 * @return
	 */
	public BooleanQuery createBooleanQuery() {
		return new BooleanQuery();
	}

	/**
	 * 添加搜索器到混合搜索器
	 * 
	 * @param booleanQuery
	 * @param occ
	 * @param query
	 */
	public void addToBooleanQuery(BooleanQuery booleanQuery, Occur occ, Query query) {
		if (booleanQuery != null && query != null && occ != null) {
			booleanQuery.add(query, occ);
		}
	}

三、搜索结果解析

 public String[] parseQuery(TopDocs topDocs,IndexSearcher search,String fieldName){
		        int hits = 0;
		        if (topDocs != null && (hits = topDocs.totalHits) > 0)
		        {
		            ScoreDoc[] docs = topDocs.scoreDocs;
		            String[] results = new String[hits];
		            for (ScoreDoc doc : docs)
		            {
		    
		                try {
		                	//通过搜索结果找到对应文档
							Document resultDoc = search.doc(doc.doc);
							List<IndexableField> list=resultDoc.getFields();
							for(IndexableField i:list)
							{
								System.out.println("名称:"+i.name()+",内容:"+i.stringValue()+",权重值:"+i.boost());
							}
						} catch (IOException e) {
						
						}
		   
		            }
		            return results;
		        }
		        return null;
		    }

四、测试搜索

Analyzer analyzer=createAnalyzer(false);
	Directory dir=createDirectory(null, "d:","dir","search");
	IndexWriterConfig conf=createIndexConf(analyzer, OpenMode.CREATE_OR_APPEND, false);
	IndexWriter index=createIndex(dir, conf);

	//创建一个文档
	Document doc=createDocument();
	 String[] states = new String[] {"欢迎来到eguid的博客", "欢迎大家来到eguid的技术博客", "欢迎大家来到eguid的技术博客,很开心能和大家一起分享开源技术"};
	//创建字段
	Field[] fields=createFields("字段名", states, TextField.TYPE_STORED, 1.1f);
	//批量增加字段到索引文档
	addFiledList(doc, fields);
	//把索引文档保存到索引器
	index.addDocument(doc);
	close(index, true);
	
	//读取目录
	IndexReader indexReader=DirectoryReader.open(dir);
	//创建索引搜索器
	IndexSearcher indexSearch=createSearch(indexReader);
	try {
		//创建文档搜索器
		Query query=createPhraseQuery(analyzer, "字段名", "eguid");
		//搜索结果
		TopDocs topDocs=search(indexSearch, query, 2);
		parseQuery(topDocs, indexSearch, "字段名");
		//得到TopDocs,这个TopDocs就是一个结果文档,里面包含了搜索的结果内容,匹配度等等搜索计算结果参数
	} catch (ParseException e) {
		
	}

搜索结果:

名称:字段名,内容:欢迎来到eguid的博客,权重值:1.0 名称:字段名,内容:欢迎大家来到eguid的技术博客,权重值:1.0 名称:字段名,内容:欢迎大家来到eguid的技术博客,很开心能和大家一起分享开源技术,权重值:1.0

到这里,lucene全文搜索的全部功能就全部实现了,而我们需要做的就是根据我们自己的业务对lucene的功能进行组合,从而实现我们的全文搜搜服务。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Dojo初探之5:dojo的request(请求)操作、请求过程事件绑定和隐藏数据data()操作(基于dojo1.11.2版本)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    eguid
  • lucene全文搜索之二:创建索引器(创建IKAnalyzer分词器和索引目录管理)基于lucene5.5.3

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    eguid
  • lucene全文搜索之一:lucene的主要功能和基本结构(基于lucene5.5.3)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    eguid
  • Windows 编程创建窗口

    #define WND_POS_X 100 #define WND_POS_Y 100 #define WND_WIDTH 500 #define WND_HE...

    用户2965768
  • 关于Linux环境变量

    最近在配置开发环境,遇到了很多不懂的问题。主要还是linux操作系统相关的,分享给宝宝们!一提到环境配置就不得不说环境变量,so,今天的主题是环境变量。

    用户3258338
  • jQuery遮罩(Mask)及弹窗时禁止页面滚动实现

    保险起见可以把 html 和 body 的高度都设置 100% ,如下,用添加 class 的方法实现:

    德顺
  • windows下安装php的redis

    至于选择用什么包,这个就看你php用的是什么版本的了,当然我的windows是64位,但我选择32位的却成功了,

    梦_之_旅
  • 基于Docker的Redis高可用集群搭建(redis-sentinel)

      之前介绍了用docker来搭建redis主从环境,但这只是对数据添加了从库备份(主从复制),当主库down掉的时候,从库是不会自动升级为主库的,也就是说,该...

    happyJared
  • Docker安装redis的使用

    1、Docker安装redis的使用。 docker search redis检索redis的服务。先检索再拉取。

    别先生
  • redis-4.0.1 源码一键安装脚本(centos 7)

    老七Linux

扫码关注云+社区

领取腾讯云代金券