use of org.apache.solr.response.ResultContext in project lucene-solr by apache.
the class QueryComponent method process.
/**
* Actually run the query
*/
@Override
public void process(ResponseBuilder rb) throws IOException {
LOG.debug("process: {}", rb.req.getParams());
SolrQueryRequest req = rb.req;
SolrParams params = req.getParams();
if (!params.getBool(COMPONENT_NAME, true)) {
return;
}
SolrIndexSearcher searcher = req.getSearcher();
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) {
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 cache
statsCache.receiveGlobalStats(req);
}
SolrQueryResponse rsp = rb.rsp;
IndexSchema schema = searcher.getSchema();
// 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).
String ids = params.get(ShardParams.IDS);
if (ids != null) {
SchemaField idField = schema.getUniqueKeyField();
List<String> idArr = StrUtils.splitSmart(ids, ",", true);
int[] luceneIds = new int[idArr.size()];
int docs = 0;
if (idField.getType().isPointField()) {
for (int i = 0; i < idArr.size(); i++) {
int id = searcher.search(idField.getType().getFieldQuery(null, idField, idArr.get(i)), 1).scoreDocs[0].doc;
if (id >= 0) {
luceneIds[docs++] = id;
}
}
} else {
for (int i = 0; i < idArr.size(); i++) {
int id = searcher.getFirstMatch(new Term(idField.getName(), idField.getType().toInternal(idArr.get(i))));
if (id >= 0)
luceneIds[docs++] = id;
}
}
DocListAndSet res = new DocListAndSet();
res.docList = new DocSlice(0, docs, luceneIds, null, docs, 0);
if (rb.isNeedDocSet()) {
// TODO: create a cache for this!
List<Query> queries = new ArrayList<>();
queries.add(rb.getQuery());
List<Query> filters = rb.getFilters();
if (filters != null)
queries.addAll(filters);
res.docSet = searcher.getDocSet(queries);
}
rb.setResults(res);
ResultContext ctx = new BasicResultContext(rb);
rsp.addResponse(ctx);
return;
}
// -1 as flag if not set.
long timeAllowed = params.getLong(CommonParams.TIME_ALLOWED, -1L);
if (null != rb.getCursorMark() && 0 < timeAllowed) {
// fundamentally incompatible
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Can not search using both " + CursorMarkParams.CURSOR_MARK_PARAM + " and " + CommonParams.TIME_ALLOWED);
}
QueryCommand cmd = rb.getQueryCommand();
cmd.setTimeAllowed(timeAllowed);
req.getContext().put(SolrIndexSearcher.STATS_SOURCE, statsCache.get(req));
QueryResult result = new QueryResult();
cmd.setSegmentTerminateEarly(params.getBool(CommonParams.SEGMENT_TERMINATE_EARLY, CommonParams.SEGMENT_TERMINATE_EARLY_DEFAULT));
if (cmd.getSegmentTerminateEarly()) {
result.setSegmentTerminatedEarly(Boolean.FALSE);
}
//
// grouping / field collapsing
//
GroupingSpecification groupingSpec = rb.getGroupingSpec();
if (groupingSpec != null) {
// not supported, silently ignore any segmentTerminateEarly flag
cmd.setSegmentTerminateEarly(false);
try {
boolean needScores = (cmd.getFlags() & SolrIndexSearcher.GET_SCORES) != 0;
if (params.getBool(GroupParams.GROUP_DISTRIBUTED_FIRST, false)) {
CommandHandler.Builder topsGroupsActionBuilder = new CommandHandler.Builder().setQueryCommand(cmd).setNeedDocSet(// Order matters here
false).setIncludeHitCount(true).setSearcher(searcher);
for (String field : groupingSpec.getFields()) {
topsGroupsActionBuilder.addCommandField(new SearchGroupsFieldCommand.Builder().setField(schema.getField(field)).setGroupSort(groupingSpec.getGroupSort()).setTopNGroups(cmd.getOffset() + cmd.getLen()).setIncludeGroupCount(groupingSpec.isIncludeGroupCount()).build());
}
CommandHandler commandHandler = topsGroupsActionBuilder.build();
commandHandler.execute();
SearchGroupsResultTransformer serializer = new SearchGroupsResultTransformer(searcher);
rsp.add("firstPhase", commandHandler.processResult(result, serializer));
rsp.add("totalHitCount", commandHandler.getTotalHitCount());
rb.setResult(result);
return;
} else if (params.getBool(GroupParams.GROUP_DISTRIBUTED_SECOND, false)) {
CommandHandler.Builder secondPhaseBuilder = new CommandHandler.Builder().setQueryCommand(cmd).setTruncateGroups(groupingSpec.isTruncateGroups() && groupingSpec.getFields().length > 0).setSearcher(searcher);
int docsToCollect = Grouping.getMax(groupingSpec.getWithinGroupOffset(), groupingSpec.getWithinGroupLimit(), searcher.maxDoc());
docsToCollect = Math.max(docsToCollect, 1);
for (String field : groupingSpec.getFields()) {
SchemaField schemaField = schema.getField(field);
String[] topGroupsParam = params.getParams(GroupParams.GROUP_DISTRIBUTED_TOPGROUPS_PREFIX + field);
if (topGroupsParam == null) {
topGroupsParam = new String[0];
}
List<SearchGroup<BytesRef>> topGroups = new ArrayList<>(topGroupsParam.length);
for (String topGroup : topGroupsParam) {
SearchGroup<BytesRef> searchGroup = new SearchGroup<>();
if (!topGroup.equals(TopGroupsShardRequestFactory.GROUP_NULL_VALUE)) {
BytesRefBuilder builder = new BytesRefBuilder();
schemaField.getType().readableToIndexed(topGroup, builder);
searchGroup.groupValue = builder.get();
}
topGroups.add(searchGroup);
}
secondPhaseBuilder.addCommandField(new TopGroupsFieldCommand.Builder().setField(schemaField).setGroupSort(groupingSpec.getGroupSort()).setSortWithinGroup(groupingSpec.getSortWithinGroup()).setFirstPhaseGroups(topGroups).setMaxDocPerGroup(docsToCollect).setNeedScores(needScores).setNeedMaxScore(needScores).build());
}
for (String query : groupingSpec.getQueries()) {
secondPhaseBuilder.addCommandField(new Builder().setDocsToCollect(docsToCollect).setSort(groupingSpec.getGroupSort()).setQuery(query, rb.req).setDocSet(searcher).build());
}
CommandHandler commandHandler = secondPhaseBuilder.build();
commandHandler.execute();
TopGroupsResultTransformer serializer = new TopGroupsResultTransformer(rb);
rsp.add("secondPhase", commandHandler.processResult(result, serializer));
rb.setResult(result);
return;
}
int maxDocsPercentageToCache = params.getInt(GroupParams.GROUP_CACHE_PERCENTAGE, 0);
boolean cacheSecondPassSearch = maxDocsPercentageToCache >= 1 && maxDocsPercentageToCache <= 100;
Grouping.TotalCount defaultTotalCount = groupingSpec.isIncludeGroupCount() ? Grouping.TotalCount.grouped : Grouping.TotalCount.ungrouped;
// this is normally from "rows"
int limitDefault = cmd.getLen();
Grouping grouping = new Grouping(searcher, result, cmd, cacheSecondPassSearch, maxDocsPercentageToCache, groupingSpec.isMain());
grouping.setGroupSort(groupingSpec.getGroupSort()).setWithinGroupSort(groupingSpec.getSortWithinGroup()).setDefaultFormat(groupingSpec.getResponseFormat()).setLimitDefault(limitDefault).setDefaultTotalCount(defaultTotalCount).setDocsPerGroupDefault(groupingSpec.getWithinGroupLimit()).setGroupOffsetDefault(groupingSpec.getWithinGroupOffset()).setGetGroupedDocSet(groupingSpec.isTruncateGroups());
if (groupingSpec.getFields() != null) {
for (String field : groupingSpec.getFields()) {
grouping.addFieldCommand(field, rb.req);
}
}
if (groupingSpec.getFunctions() != null) {
for (String groupByStr : groupingSpec.getFunctions()) {
grouping.addFunctionCommand(groupByStr, rb.req);
}
}
if (groupingSpec.getQueries() != null) {
for (String groupByStr : groupingSpec.getQueries()) {
grouping.addQueryCommand(groupByStr, rb.req);
}
}
if (rb.isNeedDocList() || rb.isDebug()) {
// we need a single list of the returned docs
cmd.setFlags(SolrIndexSearcher.GET_DOCLIST);
}
grouping.execute();
if (grouping.isSignalCacheWarning()) {
rsp.add("cacheWarning", String.format(Locale.ROOT, "Cache limit of %d percent relative to maxdoc has exceeded. Please increase cache size or disable caching.", maxDocsPercentageToCache));
}
rb.setResult(result);
if (grouping.mainResult != null) {
ResultContext ctx = new BasicResultContext(rb, grouping.mainResult);
rsp.addResponse(ctx);
rsp.getToLog().add("hits", grouping.mainResult.matches());
} else if (!grouping.getCommands().isEmpty()) {
// Can never be empty since grouping.execute() checks for this.
rsp.add("grouped", result.groupedResults);
rsp.getToLog().add("hits", grouping.getCommands().get(0).getMatches());
}
return;
} catch (SyntaxError e) {
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e);
}
}
// normal search result
searcher.search(result, cmd);
rb.setResult(result);
ResultContext ctx = new BasicResultContext(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);
}
use of org.apache.solr.response.ResultContext in project lucene-solr by apache.
the class TestRangeQuery method testRandomRangeQueries.
@Test
public void testRandomRangeQueries() throws Exception {
String handler = "";
final String[] fields = { "foo_s", "foo_i", "foo_l", "foo_f", "foo_d", "foo_ti", "foo_tl", "foo_tf", "foo_td" };
// NOTE: foo_s supports ranges, but for the arrays below we are only
// interested in fields that support *equivilent* ranges -- strings
// are not ordered the same as ints/longs, so we can't test the ranges
// for equivilence across diff fields.
//
// fields that a normal range query will work correctly on
String[] norm_fields = { "foo_i", "foo_l", "foo_f", "foo_d", "foo_ti", "foo_tl", "foo_tf", "foo_td" };
// fields that a value source range query should work on
String[] frange_fields = { "foo_i", "foo_l", "foo_f", "foo_d" };
final int l = -1 * atLeast(50);
final int u = atLeast(250);
// sometimes a very small index, sometimes a very large index
final int numDocs = random().nextBoolean() ? random().nextInt(50) : atLeast(1000);
createIndex(numDocs, new DocProcessor() {
@Override
public void process(SolrInputDocument doc) {
// 10% of the docs have missing values
if (random().nextInt(10) != 0)
addInt(doc, l, u, fields);
}
});
assertU(commit());
final int numIters = atLeast(1000);
for (int i = 0; i < numIters; i++) {
int lower = TestUtil.nextInt(random(), 2 * l, u);
int upper = TestUtil.nextInt(random(), lower, 2 * u);
boolean lowerMissing = random().nextInt(10) == 1;
boolean upperMissing = random().nextInt(10) == 1;
boolean inclusive = lowerMissing || upperMissing || random().nextBoolean();
// lower=2; upper=2; inclusive=true;
// inclusive=true; lowerMissing=true; upperMissing=true;
List<String> qs = new ArrayList<>();
for (String field : norm_fields) {
String q = field + ':' + (inclusive ? '[' : '{') + (lowerMissing ? "*" : lower) + " TO " + (upperMissing ? "*" : upper) + (inclusive ? ']' : '}');
qs.add(q);
}
for (String field : frange_fields) {
String q = "{!frange v=" + field + (lowerMissing ? "" : (" l=" + lower)) + (upperMissing ? "" : (" u=" + upper)) + (inclusive ? "" : " incl=false") + (inclusive ? "" : " incu=false") + "}";
qs.add(q);
}
String lastQ = null;
SolrQueryResponse last = null;
for (String q : qs) {
// System.out.println("QUERY="+q);
SolrQueryRequest req = req("q", q, "rows", "" + numDocs);
SolrQueryResponse qr = h.queryAndResponse(handler, req);
if (last != null) {
// we only test if the same docs matched since some queries will include factors like idf, etc.
DocList rA = ((ResultContext) qr.getResponse()).getDocList();
DocList rB = ((ResultContext) last.getResponse()).getDocList();
sameDocs(q + " vs " + lastQ, rA, rB);
}
req.close();
last = qr;
lastQ = q;
}
}
// now build some random queries (against *any* field) and validate that using it in a DBQ changes
// the index by the expected number of docs
int numDocsLeftInIndex = numDocs;
final int numDBQs = atLeast(10);
for (int i = 0; i < numDBQs; i++) {
int lower = TestUtil.nextInt(random(), 2 * l, u);
int upper = TestUtil.nextInt(random(), lower, 2 * u);
boolean lowerMissing = random().nextInt(10) == 1;
boolean upperMissing = random().nextInt(10) == 1;
boolean inclusive = lowerMissing || upperMissing || random().nextBoolean();
String dbq = null;
if (random().nextBoolean()) {
// regular range
String field = fields[random().nextInt(fields.length)];
dbq = field + ':' + (inclusive ? '[' : '{') + (lowerMissing ? "*" : lower) + " TO " + (upperMissing ? "*" : upper) + (inclusive ? ']' : '}');
} else {
// frange
String field = frange_fields[random().nextInt(frange_fields.length)];
dbq = "{!frange v=" + field + (lowerMissing ? "" : (" l=" + lower)) + (upperMissing ? "" : (" u=" + upper)) + (inclusive ? "" : " incl=false") + (inclusive ? "" : " incu=false") + "}";
}
try (SolrQueryRequest req = req("q", dbq, "rows", "0")) {
SolrQueryResponse qr = h.queryAndResponse(handler, req);
numDocsLeftInIndex -= ((ResultContext) qr.getResponse()).getDocList().matches();
}
assertU(delQ(dbq));
assertU(commit());
try (SolrQueryRequest req = req("q", "*:*", "rows", "0", "_trace_after_dbq", dbq)) {
SolrQueryResponse qr = h.queryAndResponse(handler, req);
final int allDocsFound = ((ResultContext) qr.getResponse()).getDocList().matches();
assertEquals(dbq, numDocsLeftInIndex, allDocsFound);
}
}
}
use of org.apache.solr.response.ResultContext in project lucene-solr by apache.
the class QuerySenderListener method newSearcher.
@Override
public void newSearcher(SolrIndexSearcher newSearcher, SolrIndexSearcher currentSearcher) {
final SolrIndexSearcher searcher = newSearcher;
log.info("QuerySenderListener sending requests to " + newSearcher);
List<NamedList> allLists = (List<NamedList>) getArgs().get("queries");
if (allLists == null)
return;
boolean createNewReqInfo = SolrRequestInfo.getRequestInfo() == null;
for (NamedList nlst : allLists) {
SolrQueryRequest req = null;
try {
// bind the request to a particular searcher (the newSearcher)
NamedList params = addEventParms(currentSearcher, nlst);
// for this, we default to distrib = false
if (params.get(DISTRIB) == null) {
params.add(DISTRIB, false);
}
req = new LocalSolrQueryRequest(getCore(), params) {
@Override
public SolrIndexSearcher getSearcher() {
return searcher;
}
@Override
public void close() {
}
};
SolrQueryResponse rsp = new SolrQueryResponse();
if (createNewReqInfo) {
// SolrRequerstInfo for this thread could have been transferred from the parent
// thread.
SolrRequestInfo.setRequestInfo(new SolrRequestInfo(req, rsp));
}
getCore().execute(getCore().getRequestHandler(req.getParams().get(CommonParams.QT)), req, rsp);
// Retrieve the Document instances (not just the ids) to warm
// the OS disk cache, and any Solr document cache. Only the top
// level values in the NamedList are checked for DocLists.
NamedList values = rsp.getValues();
for (int i = 0; i < values.size(); i++) {
Object o = values.getVal(i);
if (o instanceof ResultContext) {
o = ((ResultContext) o).getDocList();
}
if (o instanceof DocList) {
DocList docs = (DocList) o;
for (DocIterator iter = docs.iterator(); iter.hasNext(); ) {
newSearcher.doc(iter.nextDoc());
}
}
}
} catch (Exception e) {
// do nothing... we want to continue with the other requests.
// the failure should have already been logged.
} finally {
if (req != null)
req.close();
if (createNewReqInfo)
SolrRequestInfo.clearRequestInfo();
}
}
log.info("QuerySenderListener done.");
}
use of org.apache.solr.response.ResultContext in project ORCID-Source by ORCID.
the class OrcidProfileResponseWriter method write.
@Override
public void write(Writer writer, SolrQueryRequest request, SolrQueryResponse response) throws IOException {
ResultContext resultContext = (ResultContext) response.getValues().get("response");
DocIterator iterator = resultContext.docs.iterator();
if (iterator.hasNext()) {
int docId = iterator.nextDoc();
Document doc = request.getSearcher().doc(docId);
IndexableField field = doc.getField("public-profile-message");
writer.append(field.stringValue());
} else
throw new SolrException(SolrException.ErrorCode.NOT_FOUND, "No record found for reponse writer");
}
use of org.apache.solr.response.ResultContext in project SearchServices by Alfresco.
the class Cloud method getDocList.
/**
* Returns the doc list resulting from running the query
* @param requestHandler the handler that handles the request
* @param request the request object to put the query on
* @param query the string that specifies the docs
* @return the docs that come back from the query
*/
DocList getDocList(SolrRequestHandler requestHandler, SolrQueryRequest request, String query) {
// Getting the doc list is shard-specific, and not really cloud-friendly
ModifiableSolrParams params = new ModifiableSolrParams(request.getParams());
// Sets MAX_VALUE to get all the rows
params.set("q", query).set("fl", QueryConstants.FIELD_SOLR4_ID).set("rows", Integer.MAX_VALUE);
ResultContext rc = this.getResultContext(requestHandler, request, params);
return rc != null ? rc.getDocList() : null;
}
Aggregations