一步一步跟我学习lucene(16)---lucene搜索之facet查询查询示例(2)

本篇是接一步一步跟我学习lucene(14)---lucene搜索之facet索引原理和facet查询实例(http://blog.csdn.net/wuyinggui10000/article/details/45973769),上篇主要是统计facet的dim和每个种类对应的数量,个人感觉这个跟lucene的group不同的在于facet的存储类似于hash(key-field-value)形式的,而group则是单一的map(key-value)形式的,虽然都可以统计某一品类的数量,显然facet更具扩展性。

key-field-value查询

facet可以对某一个维度的满足某个条件的结果进行统计,如下:

 @Test
 public void testDrillDownSlide(){
  try {
   DirectoryReader indexReader = DirectoryReader.open(directory);
   IndexSearcher searcher = new IndexSearcher(indexReader);
   DrillSideways ds = new DrillSideways(searcher, config, taxoReader);
   DrillDownQuery ddq = new DrillDownQuery(config);
   ddq.add("filePath", "ik");
   DrillSidewaysResult r = ds.search(ddq, 10);
   TopDocs hits = r.hits;
   for (ScoreDoc scoreDoc : hits.scoreDocs) {
    Document doc = searcher.doc(scoreDoc.doc);
    System.out.println(doc.get("path"));
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

这里我们搜索的dim是filePath,查找的范围是ik相关联的数据,对应的查询结果就是所有包含在IK文件夹下的数据

C:\Users\lenovo\Desktop\lucene\IK-Analyzer-2012FF\dist\IKAnalyzer.cfg.xml
C:\Users\lenovo\Desktop\lucene\IK-Analyzer-2012FF\dist\IKAnalyzer2012FF_u1.jar
C:\Users\lenovo\Desktop\lucene\IK-Analyzer-2012FF\dist\IKAnalyzer2015.jar
C:\Users\lenovo\Desktop\lucene\IK-Analyzer-2012FF\dist\LICENSE.txt
C:\Users\lenovo\Desktop\lucene\IK-Analyzer-2012FF\dist\NOTICE.txt
C:\Users\lenovo\Desktop\lucene\IK-Analyzer-2012FF\dist\stopword.dic
C:\Users\lenovo\Desktop\lucene\IK-Analyzer-2012FF\doc\allclasses-frame.html
C:\Users\lenovo\Desktop\lucene\IK-Analyzer-2012FF\doc\allclasses-noframe.html
C:\Users\lenovo\Desktop\lucene\IK-Analyzer-2012FF\doc\constant-values.html
C:\Users\lenovo\Desktop\lucene\IK-Analyzer-2012FF\doc\deprecated-list.html

range查询

facet还支持range查询,range查询的类型包括DoubleRange和LongRange;其对应的Facets为DoubleRangeFacets和LongRangeFacets;

以LongRangeFacetCounts为例,LongRangeFacetCounts可以对long类型的数值进行整理查询

这里我们对每个文档的单词数量进行区间的分组,range查询示例如下:

	@Test
	public void testOverlappedEndStart(){
		try {
			IndexReader reader = DirectoryReader.open(directory);
			FacetsCollector fc = new FacetsCollector();
		    IndexSearcher s = new IndexSearcher(reader);
		    s.search(new MatchAllDocsQuery(), fc);
		    Facets facets = new LongRangeFacetCounts("contentLength", fc,
		            new LongRange("0-100", 0L, true, 100L, true),
		            new LongRange("100-200", 100L, true, 200L, true),
		            new LongRange("200-300", 200L, true, 300L, true),
		            new LongRange("300-400", 300L, true, 400L, true));
		    FacetResult result = facets.getTopChildren(10, "contentLength");
		    System.out.println(result.toString());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

其执行结果为:

dim=contentLength path=[] value=22 childCount=4
  0-100 (7)
  100-200 (9)
  200-300 (3)
  300-400 (3)

多个dim查询

facet里DrillSideways可以定义多个facetCount的查询,这时返回的结果为各个facet对应的统计数

	@Test
	public void testMixedRangeAndNonRangeTaxonomy(){
		try {
			IndexReader reader = DirectoryReader.open(directory);
		    IndexSearcher s = new IndexSearcher(reader);
		    DrillSideways ds = new DrillSideways(s, config, taxoReader){
		        @Override
		        protected Facets buildFacetsResult(FacetsCollector drillDowns, FacetsCollector[] drillSideways, String[] drillSidewaysDims) throws IOException {
		          FacetsCollector fieldFC = drillDowns;
		          FacetsCollector dimFC = drillDowns;
		          if (drillSideways != null) {
		            for(int i=0;i<drillSideways.length;i++) {
		              String dim = drillSidewaysDims[i];
		              if (dim.equals("contentLength")) {
		                fieldFC = drillSideways[i];
		              } else {
		            	dimFC = drillSideways[i];
		              }
		            }
		          }
		          Map<String,Facets> byDim = new HashMap<String,Facets>();
		          byDim.put("contentLength",new LongRangeFacetCounts("contentLength", fieldFC,
		                          new LongRange("less than 100", 0L, true, 100L, false),
		                          new LongRange("between 100 and 200", 100L, true, 200L, false),
		                          new LongRange("over 200", 200L, true, Integer.MAX_VALUE, false)));
		          byDim.put("dim", new FastTaxonomyFacetCounts(taxoReader, config, dimFC));
		          return new MultiFacets(byDim);
		        }

		        @Override
		        protected boolean scoreSubDocsAtOnce() {
		          return false;
		        }
		    };
		    DrillDownQuery ddq = new DrillDownQuery(config);
		    DrillSidewaysResult dsr = ds.search(ddq, 10);
		    Facets facet = dsr.facets;
		    List<FacetResult> results = facet.getAllDims(reader.maxDoc());
		    for (FacetResult facetResult : results) {
				System.out.println(facetResult.dim);
				LabelAndValue[] values = facetResult.labelValues;
				for (LabelAndValue labelAndValue : values) {
					System.out.println("\t"+labelAndValue.label +"       "+labelAndValue.value);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

程序运行结果如下:

dim
	odd       126
	even       119
contentLength
	less than 100       7
	between 100 and 200       9
	over 200       229

对单个range的列表查询支持

facet支持单个range的区间查询,这样可以查询出此range对饮的TopDocs列表,等同于返回了document对象列表;

这里我们查询内容长度在0到100之间的数据

	@Test
	public void testDrillDownQueryWithRange(){
		try {
			IndexReader reader = DirectoryReader.open(directory);
		    IndexSearcher s = new IndexSearcher(reader);
		    DrillDownQuery ddq = new DrillDownQuery(config);
		    ddq.add("contentLength", NumericRangeQuery.newLongRange("contentLength", 0l, 100l, true, false));//;
		    TopDocs docs = s.search(ddq, reader.maxDoc());
		    System.out.println("查询到的数据总数:"+docs.totalHits);
		    for (ScoreDoc scoreDoc : docs.scoreDocs) {
				System.out.println(s.doc(scoreDoc.doc).get("path"));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	

其运行结果如下:

查询到的数据总数:7
C:\Users\lenovo\Desktop\lucene\jcseg\DONATE.txt
C:\Users\lenovo\Desktop\lucene\jcseg\jcseg-elasticsearch\src\main\resources\es-plugin.properties
C:\Users\lenovo\Desktop\lucene\jcseg\lexicon\lex-autoload.todo
C:\Users\lenovo\Desktop\lucene\jcseg\lexicon\lex-en-pun.lex
C:\Users\lenovo\Desktop\lucene\jcseg\lexicon\lex-ln-adorn.lex
C:\Users\lenovo\Desktop\lucene\IK-Analyzer-2012FF\doc\resources\inherit.gif
C:\Users\lenovo\Desktop\lucene\IK-Analyzer-2012FF\src\ext.dic

本节内容都是示例,个人觉得这种会比较直观些,facet涉及的面比较广,这里没有facet的sort和其他相关操作,会在后续补上,希望大家持续关注。



时间: 2024-10-22 21:21:49

一步一步跟我学习lucene(16)---lucene搜索之facet查询查询示例(2)的相关文章

一步一步跟我学习lucene(19)---lucene增量更新和NRT(near-real-time)Query近实时查询

这两天加班,不能兼顾博客的更新,请大家见谅. 有时候我们创建完索引之后,数据源可能有更新的内容,而我们又想像数据库那样能直接体现在查询中,这里就是我们所说的增量索引.对于这样的需求我们怎么来实现呢?lucene内部是没有提供这种增量索引的实现的: 这里我们一般可能会想到,将之前的索引全部删除,然后进行索引的重建.对于这种做法,如果数据源的条数不是特别大的情况下倒还可以,如果数据源的条数特别大的话,势必会造成查询数据耗时,同时索引的构建也是比较耗时的,几相叠加,势必可能造成查询的时候数据缺失的情况

一步一步跟我学习lucene(9)---lucene搜索之拼写检查和相似度查询提示(spellcheck)

suggest应用场景 用户的输入行为是不确定的,而我们在写程序的时候总是想让用户按照指定的内容或指定格式的内容进行搜索,这里就要进行人工干预用户输入的搜索条件了:我们在用百度谷歌等搜索引擎的时候经常会看到按键放下的时候直接会提示用户是否想搜索某些相关的内容,恰好lucene在开发的时候想到了这一点,lucene提供的suggest包正是用来解决上述问题的. suggest包联想词相关介绍 suggest包提供了lucene的自动补全或者拼写检查的支持: 拼写检查相关的类在org.apache.

一步一步跟我学习lucene(13)---lucene搜索之自定义排序的实现原理和编写自己的自定义排序工具

自定义排序说明 我们在做lucene搜索的时候,可能会需要排序功能,虽然lucene内置了多种类型的排序,但是如果在需要先进行某些值的运算然后在排序的时候就有点显得无能为力了: 要做自定义查询,我们就要研究lucene已经实现的排序功能,lucene的所有排序都是要继承FieldComparator,然后重写内部实现,这里以IntComparator为例子来查看其实现: IntComparator相关实现 其类的声明为 public static class IntComparator exte

一步一步跟我学习lucene(14)---lucene搜索之facet查询原理和facet查询实例

Facet说明 我们在浏览网站的时候,经常会遇到按某一类条件查询的情况,这种情况尤以电商网站最多,以天猫商城为例,我们选择某一个品牌,系统会将该品牌对应的商品展示出来,效果图如下: 如上图,我们关注的是品牌,选购热点等方面,对于类似的功能我们用lucene的term查询当然可以,但是在数据量特别大的情况下还用普通查询来实现显然会因为FSDirectory.open等耗时的操作造成查询效率的低下,同时普通查询是全部document都扫描一遍,这样显然造成了查询效率低: lucene提供了facet

一步一步跟我学习lucene(12)---lucene搜索之分组处理group查询

grouping介绍 我们在做lucene搜索的时候,可能会用到对某个条件的数据进行统计,比如统计有多少个省份,在sql查询中我们可以用distinct来完成类似的功能,也可以用group by来对查询的列进行分组查询.在lucene中我们实现类似的功能怎么做呢,比较费时的做法时我们查询出所有的结果,然后对结果里边的省份对应的field查询出来,往set里边放,显然这种做法效率低,不可取:lucene为了解决上述问题,提供了用于分组操作的模块group,group主要用户处理不同lucene中含

一步一步跟我学习lucene(11)---lucene搜索之高亮显示highlighter

highlighter介绍 这几天一直加班,博客有三天没有更新了,望见谅:我们在做查询的时候,希望对我们自己的搜索结果与搜索内容相近的地方进行着重显示,就如下面的效果 这里我们搜索的内容是"一步一步跟我学习lucene",搜索引擎展示的结果中对用户的输入信息进行了配色方面的处理,这种区分正常文本和输入内容的效果即是高亮显示: 这样做的好处: 视觉上让人便于查找有搜索对应的文本块: 界面展示更友好: lucene提供了highlighter插件来体现类似的效果: highlighter对

一步一步跟我学习lucene(10)---lucene搜索之联想词提示之suggest原理和应用

昨天了解了suggest包中的spell相关的内容,主要是拼写检查和相似度查询提示: 今天准备了解下关于联想词的内容,lucene的联想词是在org.apache.lucene.search.suggest包下边,提供了自动补全或者联想提示功能的支持: InputIterator说明 InputIterator是一个支持枚举term,weight,payload三元组的供suggester使用的接口,目前仅支持AnalyzingSuggester,FuzzySuggester andAnalyz

一步一步跟我学习lucene(7)---lucene搜索之IndexSearcher构建过程

最近一直在写一步一步跟我学习lucene系列(http://blog.csdn.net/wuyinggui10000/article/category/3173543),个人的博客也收到了很多的访问量,谢谢大家的关注,这也是对我个人的一个激励,O(∩_∩)O哈哈~,个人感觉在博客的编写过程中自己收获了很多,我会一直继续下去,在工作的过程中自己也会写出更多类似系列的博客,也算是对自己只是的一种积累: IndexSearcher 搜索引擎的构建分为索引内容和查询索引两个大方面,这里要介绍的是luce

一步一步跟我学习lucene(17)---lucene搜索之expressions表达式处理

有时候我们在做lucene的结果展示的时候可能需要对多个列的内容进行计算,根据多个field对应的值做数值方面的运算. lucene自4.6版本起,提供了用于运算的expression模块: expression分为两部分: org.apache.lucene.expressions:提供了字段绑定和相关的表达式参数传递的功能: org.apache.lucene.expressions.js:提供了表达式定义的功能. Expression类使用示例 Expression是提供document的