Fix bug in single shard optimization when sorting documents in search request
This commit adds a function to shard-level query result to determine whether there are any hits that needs fetching. Currently, a shard-level query result can have hits when there are search hits and/or completion suggestion hits. The newly added function encapsulates the checks to determine if a shard-level query result has any fetchable hits, which is used in optimizing for sorting documents and releasing search request contexts.
This commit is contained in:
parent
7542ef3173
commit
40d7ebc515
|
@ -322,11 +322,8 @@ abstract class AbstractSearchAsyncAction<FirstResult extends SearchPhaseResult>
|
||||||
// we only release search context that we did not fetch from if we are not scrolling
|
// we only release search context that we did not fetch from if we are not scrolling
|
||||||
if (request.scroll() == null) {
|
if (request.scroll() == null) {
|
||||||
for (AtomicArray.Entry<? extends QuerySearchResultProvider> entry : queryResults.asList()) {
|
for (AtomicArray.Entry<? extends QuerySearchResultProvider> entry : queryResults.asList()) {
|
||||||
QuerySearchResult queryResult = entry.value.queryResult().queryResult();
|
QuerySearchResult queryResult = entry.value.queryResult();
|
||||||
final TopDocs topDocs = queryResult.topDocs();
|
if (queryResult.hasHits()
|
||||||
final Suggest suggest = queryResult.suggest();
|
|
||||||
if (((topDocs != null && topDocs.scoreDocs.length > 0) // the shard had matches
|
|
||||||
||suggest != null && suggest.hasScoreDocs()) // or had suggest docs
|
|
||||||
&& docIdsToLoad.get(entry.index) == null) { // but none of them made it to the global top docs
|
&& docIdsToLoad.get(entry.index) == null) { // but none of them made it to the global top docs
|
||||||
try {
|
try {
|
||||||
DiscoveryNode node = nodes.get(entry.value.queryResult().shardTarget().nodeId());
|
DiscoveryNode node = nodes.get(entry.value.queryResult().shardTarget().nodeId());
|
||||||
|
|
|
@ -269,7 +269,7 @@ public class SearchService extends AbstractLifecycleComponent implements IndexEv
|
||||||
|
|
||||||
loadOrExecuteQueryPhase(request, context);
|
loadOrExecuteQueryPhase(request, context);
|
||||||
|
|
||||||
if (hasHits(context.queryResult()) == false && context.scrollContext() == null) {
|
if (context.queryResult().hasHits() == false && context.scrollContext() == null) {
|
||||||
freeContext(context.id());
|
freeContext(context.id());
|
||||||
} else {
|
} else {
|
||||||
contextProcessedSuccessfully(context);
|
contextProcessedSuccessfully(context);
|
||||||
|
@ -324,7 +324,7 @@ public class SearchService extends AbstractLifecycleComponent implements IndexEv
|
||||||
operationListener.onPreQueryPhase(context);
|
operationListener.onPreQueryPhase(context);
|
||||||
long time = System.nanoTime();
|
long time = System.nanoTime();
|
||||||
queryPhase.execute(context);
|
queryPhase.execute(context);
|
||||||
if (hasHits(context.queryResult()) == false && context.scrollContext() == null) {
|
if (context.queryResult().hasHits() == false && context.scrollContext() == null) {
|
||||||
// no hits, we can release the context since there will be no fetch phase
|
// no hits, we can release the context since there will be no fetch phase
|
||||||
freeContext(context.id());
|
freeContext(context.id());
|
||||||
} else {
|
} else {
|
||||||
|
@ -861,11 +861,6 @@ public class SearchService extends AbstractLifecycleComponent implements IndexEv
|
||||||
context.docIdsToLoad(docIdsToLoad, 0, docIdsToLoad.length);
|
context.docIdsToLoad(docIdsToLoad, 0, docIdsToLoad.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean hasHits(final QuerySearchResult searchResult) {
|
|
||||||
return searchResult.topDocs().scoreDocs.length > 0 ||
|
|
||||||
(searchResult.suggest() != null && searchResult.suggest().hasScoreDocs());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processScroll(InternalScrollSearchRequest request, SearchContext context) {
|
private void processScroll(InternalScrollSearchRequest request, SearchContext context) {
|
||||||
// process scroll
|
// process scroll
|
||||||
context.from(context.from() + context.size());
|
context.from(context.from() + context.size());
|
||||||
|
|
|
@ -181,7 +181,7 @@ public class SearchPhaseController extends AbstractComponent {
|
||||||
} else {
|
} else {
|
||||||
// lets see if we only got hits from a single shard, if so, we can optimize...
|
// lets see if we only got hits from a single shard, if so, we can optimize...
|
||||||
for (AtomicArray.Entry<? extends QuerySearchResultProvider> entry : results) {
|
for (AtomicArray.Entry<? extends QuerySearchResultProvider> entry : results) {
|
||||||
if (entry.value.queryResult().topDocs().scoreDocs.length > 0) {
|
if (entry.value.queryResult().hasHits()) {
|
||||||
if (result != null) { // we already have one, can't really optimize
|
if (result != null) { // we already have one, can't really optimize
|
||||||
canOptimize = false;
|
canOptimize = false;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -188,6 +188,12 @@ public class QuerySearchResult extends QuerySearchResultProvider {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns true iff the result has hits */
|
||||||
|
public boolean hasHits() {
|
||||||
|
return (topDocs != null && topDocs.scoreDocs.length > 0) ||
|
||||||
|
(suggest != null && suggest.hasScoreDocs());
|
||||||
|
}
|
||||||
|
|
||||||
public static QuerySearchResult readQuerySearchResult(StreamInput in) throws IOException {
|
public static QuerySearchResult readQuerySearchResult(StreamInput in) throws IOException {
|
||||||
QuerySearchResult result = new QuerySearchResult();
|
QuerySearchResult result = new QuerySearchResult();
|
||||||
result.readFrom(in);
|
result.readFrom(in);
|
||||||
|
|
Loading…
Reference in New Issue