solr的facet源码解读(一)——facet.query
程序员文章站
2022-04-03 19:16:06
...
solr的facet query意思很简单,表示在所有的搜索到的结果中,符合某个query的doc有多少个。他的实现原理也很简单。
solr中所有的facet的操作都在facetComponent中,在这个类的process方法里面,会将facet委托给SimpleFacet这个类,然后调用simpleFacet.getFacetCounts方法。我们要说的facet.query就是在这个类中,如下:
public NamedList<Object> getFacetCounts() { // if someone called this method, benefit of the doubt: assume true if (!params.getBool(FacetParams.FACET, true)) return null; facetResponse = new SimpleOrderedMap<>(); try { facetResponse.add("facet_queries", getFacetQueryCounts()); facetResponse.add("facet_fields", getFacetFieldCounts()); // facetResponse.add("facet_ranges", getFacetRangeCounts()); facetResponse.add("facet_intervals", getFacetIntervalCounts()); } catch (IOException e) { throw new SolrException(ErrorCode.SERVER_ERROR, e); } catch (SyntaxError e) { throw new SolrException(ErrorCode.BAD_REQUEST, e); } return facetResponse; }
可以发现,所有的facet的操作都是在这个类中,包括facetQuery、facetField、facetRange,在工作中最常用的就是facetQuery、facetField,先看下facetQuery吧
public NamedList<Integer> getFacetQueryCounts() throws IOException, SyntaxError { NamedList<Integer> res = new SimpleOrderedMap<>(); String[] facetQs = params.getParams(FacetParams.FACET_QUERY); if (null != facetQs && 0 != facetQs.length) { for (String q : facetQs) {//轮训所有的facet的query parseParams(FacetParams.FACET_QUERY, q);//这个方法很简单,就是将一些参数保存到这个类的属性里面,比如下面的docs, // TODO: slight optimization would prevent double-parsing of any localParams Query qobj = QParser.getParser(q, null, req).getQuery();//获得facet.query的query是什么。 if (qobj == null) { res.add(key, 0); } else if (params.getBool(GroupParams.GROUP_FACET, false)) {//这个我没有看,因为工作中还没有遇到这个功能。以后很可能会补充上。 res.add(key, getGroupedFacetQueryCount(qobj)); } else { res.add(key, searcher.numDocs(qobj, docs));//searcher.numDocs很简单,就是使用这个qobj命中的docs和第二个参数docs取交集,返回的是交集中的数量,第二个参数是solr的参数中q和fq中的命中的doc的id的集合。并且这个方法中会使用filterCache,所以facet.query是很高效的,它仅仅会涉及到倒排表的合并,并且还会使用到filterCache。 } } } return res; }
如此简单就看懂了facet.query的实现原理,他的实现还是很高效的,可以大胆的使用。