如何使用Lucene来实现Solr的facet.missing = true

时间:2018-11-19 12:19:28

标签: lucene facet

Solr支持返回数字matching documents with no facet value for the field。用Lucene如何实现相同的目的?

示例:我有5个文档,它们可能具有字段category

的值
  • 文档1具有category=A
  • 文档2具有category=Acategory=B
  • 文档3具有category=Bcategory=C
  • 文档4和5没有category

代码看起来像

 var facetsCollector = new FacetsCollector();
 FacetsCollector.Search(_indexSearcher, new MatchAllDocsQuery(), 100, facetsCollector);
 var state = DefaultSortedSetDocValuesReaderState(_indexReader, "category_facet");
 var facets = SortedSetDocValuesFacetCounts(state, facetsCollector);
 var children = facets.GetTopChildren(100, "category_dim");

这给了我LabelValues

  • 标签:A,值:2
  • 标签:B,值:2
  • 标签:C,值:1

如何确定“标签:(缺失),值:2”?

运行另一个查询+*:* -category:*是显而易见的选择。但是,可以用更聪明的方式做到吗?

1 个答案:

答案 0 :(得分:0)

只需执行以下操作即可完成Solr facet.missing功能:

SchemaField sf = searcher.getSchema().getField(fieldName);
DocSet hasVal = searcher.getDocSet(sf.getType().getRangeQuery(null, sf, null, null, false, false));
return docs.andNotSize(hasVal);

基本上意味着-使用搜索之前提供的文档集,通过运行范围查询获得另一个文档集,范围查询只查找缺少值的文档,然后应用简单的布尔操作。

不幸的是,Lucene没有内置的DocSet功能,因此需要一些技巧。我可以想到这样的东西:

Query q = some Lucene query
Set<Integer> queryRes = new HashSet<>();
searcher.search(q, new CheckHits.SetCollector(queryRes));

Set<Integer> missingRes = new HashSet<>();
searcher.search(new TermRangeQuery("category", null, null, false, false), new CheckHits.SetCollector(missingRes));
missingRes.retainAll(queryRes);

System.out.println(missingRes.size());

HashSet保留功能在速度方面应该还可以。如果进一步需要,可以将该收集器扩展为以更有效的方式存储ID

可以找到完整的示例there