4.4.10 QueryComponent
/** * Actually run the query */@Override public void process(ResponseBuilder rb) throwsIOException { LOG.debug("process: {}", rb.req.getParams()); SolrQueryRequest req =rb.req; SolrParams params =req.getParams(); if (!params.getBool(COMPONENT_NAME, true)) { return; } StatsCache statsCache =req.getCore().getStatsCache(); int purpose =params.getInt(ShardParams.SHARDS_PURPOSE, ShardRequest.PURPOSE_GET_TOP_IDS); if ((purpose & ShardRequest.PURPOSE_GET_TERM_STATS) != 0) { SolrIndexSearcher searcher =req.getSearcher(); statsCache.returnLocalStats(rb, searcher); return; } // check if we need to update the local copy of global dfs if ((purpose & ShardRequest.PURPOSE_SET_TERM_STATS) != 0) { // retrieve from request and update local cachestatsCache.receiveGlobalStats(req); } // Optional: This could also be implemented by the top-level searcher sending // a filter that lists the ids... that would be transparent to // the request handler, but would be more expensive (and would preserve score // too if desired). if(doProcessSearchByIds(rb)) { return; } // -1 as flag if not set. long timeAllowed = params.getLong(CommonParams.TIME_ALLOWED, -1L); if (null != rb.getCursorMark() && 0
}
4.4.11 SolrIndexSearcher
private void doProcessUngroupedSearch(ResponseBuilder rb, QueryCommand cmd, QueryResult result) throwsIOException { SolrQueryRequest req =rb.req; SolrQueryResponse rsp =rb.rsp; SolrIndexSearcher searcher =req.getSearcher(); searcher.search(result, cmd); rb.setResult(result); ResultContext ctx = newBasicResultContext(rb); rsp.addResponse(ctx); rsp.getToLog().add("hits", rb.getResults().docList.matches()); if ( ! rb.req.getParams().getBool(ShardParams.IS_SHARD,false) ) { if (null !=rb.getNextCursorMark()) { rb.rsp.add(CursorMarkParams.CURSOR_MARK_NEXT, rb.getNextCursorMark().getSerializedTotem()); } } if(rb.mergeFieldHandler != null) { rb.mergeFieldHandler.handleMergeFields(rb, searcher); } else {
doFieldSortValues(rb, searcher);
}
doPrefetch(rb);
}
4.4.12SolrIndexSearcher
/** * Builds the necessary collector chain (via delegate wrapping) and executes the query against it. This method takes * into consideration both the explicitly provided collector and postFilter as well as any needed collector wrappers * for dealing with options specified in the QueryCommand. */ private voidbuildAndRunCollectorChain(QueryResult qr, Query query, Collector collector, QueryCommand cmd, DelegatingCollector postFilter) throwsIOException { EarlyTerminatingSortingCollector earlyTerminatingSortingCollector = null; if(cmd.getSegmentTerminateEarly()) { final Sort cmdSort =cmd.getSort(); final int cmdLen =cmd.getLen(); final Sort mergeSort =core.getSolrCoreState().getMergePolicySort(); if (cmdSort == null || cmdLen <= 0 || mergeSort == null || !EarlyTerminatingSortingCollector.canEarlyTerminate(cmdSort, mergeSort)) { log.warn("unsupported combination: segmentTerminateEarly=true cmdSort={} cmdLen={} mergeSort={}", cmdSort, cmdLen, mergeSort); } else{ collector = earlyTerminatingSortingCollector = newEarlyTerminatingSortingCollector(collector, cmdSort, cmd.getLen()); } } final boolean terminateEarly =cmd.getTerminateEarly(); if(terminateEarly) { collector = newEarlyTerminatingCollector(collector, cmd.getLen()); } final long timeAllowed =cmd.getTimeAllowed(); if (timeAllowed > 0) { collector = newTimeLimitingCollector(collector, TimeLimitingCollector.getGlobalCounter(), timeAllowed); } if (postFilter != null) { postFilter.setLastDelegate(collector); collector =postFilter; } try{ super.search(query, collector); } catch (TimeLimitingCollector.TimeExceededException |ExitableDirectoryReader.ExitingReaderException x) { log.warn("Query: [{}]; {}", query, x.getMessage()); qr.setPartialResults(true); } catch(EarlyTerminatingCollectorException etce) { if (collector instanceofDelegatingCollector) { ((DelegatingCollector) collector).finish(); } throwetce; } finally{ if (earlyTerminatingSortingCollector != null) { qr.setSegmentTerminatedEarly(earlyTerminatingSortingCollector.terminatedEarly()); } } if (collector instanceof DelegatingCollector) {
((DelegatingCollector) collector).finish();
}
}
5.总结
从solr-lucene架构图所示,solr封装了handler来处理各种请求,底下是SearchComponent,分为pre,process,post三阶段处理,后调用lucene的底层api。
lucene 底层通过Similarity来完成打分过程,详细介绍了lucene的底层文件结构,和一步步如何实现打分。
参考资料: