Search in sources :

Example 1 with FetchSearchResult

use of org.elasticsearch.search.fetch.FetchSearchResult in project elasticsearch by elastic.

the class SearchPhaseControllerTests method generateFetchResults.

private AtomicArray<QuerySearchResultProvider> generateFetchResults(int nShards, ScoreDoc[] mergedSearchDocs, Suggest mergedSuggest) {
    AtomicArray<QuerySearchResultProvider> fetchResults = new AtomicArray<>(nShards);
    for (int shardIndex = 0; shardIndex < nShards; shardIndex++) {
        float maxScore = -1F;
        SearchShardTarget shardTarget = new SearchShardTarget("", new Index("", ""), shardIndex);
        FetchSearchResult fetchSearchResult = new FetchSearchResult(shardIndex, shardTarget);
        List<SearchHit> searchHits = new ArrayList<>();
        for (ScoreDoc scoreDoc : mergedSearchDocs) {
            if (scoreDoc.shardIndex == shardIndex) {
                searchHits.add(new SearchHit(scoreDoc.doc, "", new Text(""), Collections.emptyMap()));
                if (scoreDoc.score > maxScore) {
                    maxScore = scoreDoc.score;
                }
            }
        }
        for (Suggest.Suggestion<?> suggestion : mergedSuggest) {
            if (suggestion instanceof CompletionSuggestion) {
                for (CompletionSuggestion.Entry.Option option : ((CompletionSuggestion) suggestion).getOptions()) {
                    ScoreDoc doc = option.getDoc();
                    if (doc.shardIndex == shardIndex) {
                        searchHits.add(new SearchHit(doc.doc, "", new Text(""), Collections.emptyMap()));
                        if (doc.score > maxScore) {
                            maxScore = doc.score;
                        }
                    }
                }
            }
        }
        SearchHit[] hits = searchHits.toArray(new SearchHit[searchHits.size()]);
        fetchSearchResult.hits(new SearchHits(hits, hits.length, maxScore));
        fetchResults.set(shardIndex, fetchSearchResult);
    }
    return fetchResults;
}
Also used : AtomicArray(org.elasticsearch.common.util.concurrent.AtomicArray) CompletionSuggestion(org.elasticsearch.search.suggest.completion.CompletionSuggestion) QuerySearchResultProvider(org.elasticsearch.search.query.QuerySearchResultProvider) SearchHit(org.elasticsearch.search.SearchHit) FetchSearchResult(org.elasticsearch.search.fetch.FetchSearchResult) ArrayList(java.util.ArrayList) Index(org.elasticsearch.index.Index) Text(org.elasticsearch.common.text.Text) Suggest(org.elasticsearch.search.suggest.Suggest) ScoreDoc(org.apache.lucene.search.ScoreDoc) SearchShardTarget(org.elasticsearch.search.SearchShardTarget) SearchHits(org.elasticsearch.search.SearchHits)

Example 2 with FetchSearchResult

use of org.elasticsearch.search.fetch.FetchSearchResult in project elasticsearch by elastic.

the class SearchScrollQueryThenFetchAsyncAction method executeFetchPhase.

private void executeFetchPhase() throws Exception {
    sortedShardDocs = searchPhaseController.sortDocs(true, queryResults);
    if (sortedShardDocs.length == 0) {
        finishHim(searchPhaseController.reducedQueryPhase(queryResults.asList()));
        return;
    }
    final IntArrayList[] docIdsToLoad = searchPhaseController.fillDocIdsToLoad(queryResults.length(), sortedShardDocs);
    SearchPhaseController.ReducedQueryPhase reducedQueryPhase = searchPhaseController.reducedQueryPhase(queryResults.asList());
    final ScoreDoc[] lastEmittedDocPerShard = searchPhaseController.getLastEmittedDocPerShard(reducedQueryPhase, sortedShardDocs, queryResults.length());
    final AtomicInteger counter = new AtomicInteger(docIdsToLoad.length);
    for (int i = 0; i < docIdsToLoad.length; i++) {
        final int index = i;
        final IntArrayList docIds = docIdsToLoad[index];
        if (docIds != null) {
            final QuerySearchResult querySearchResult = queryResults.get(index);
            ScoreDoc lastEmittedDoc = lastEmittedDocPerShard[index];
            ShardFetchRequest shardFetchRequest = new ShardFetchRequest(querySearchResult.id(), docIds, lastEmittedDoc);
            DiscoveryNode node = nodes.get(querySearchResult.shardTarget().getNodeId());
            searchTransportService.sendExecuteFetchScroll(node, shardFetchRequest, task, new ActionListener<FetchSearchResult>() {

                @Override
                public void onResponse(FetchSearchResult result) {
                    result.shardTarget(querySearchResult.shardTarget());
                    fetchResults.set(index, result);
                    if (counter.decrementAndGet() == 0) {
                        finishHim(reducedQueryPhase);
                    }
                }

                @Override
                public void onFailure(Exception t) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Failed to execute fetch phase", t);
                    }
                    successfulOps.decrementAndGet();
                    if (counter.decrementAndGet() == 0) {
                        finishHim(reducedQueryPhase);
                    }
                }
            });
        } else {
            // the counter is set to the total size of docIdsToLoad which can have null values so we have to count them down too
            if (counter.decrementAndGet() == 0) {
                finishHim(reducedQueryPhase);
            }
        }
    }
}
Also used : DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) FetchSearchResult(org.elasticsearch.search.fetch.FetchSearchResult) ShardFetchRequest(org.elasticsearch.search.fetch.ShardFetchRequest) ScoreDoc(org.apache.lucene.search.ScoreDoc) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ScrollQuerySearchResult(org.elasticsearch.search.query.ScrollQuerySearchResult) QuerySearchResult(org.elasticsearch.search.query.QuerySearchResult) IntArrayList(com.carrotsearch.hppc.IntArrayList)

Example 3 with FetchSearchResult

use of org.elasticsearch.search.fetch.FetchSearchResult in project elasticsearch by elastic.

the class SearchPhaseController method getHits.

private SearchHits getHits(ReducedQueryPhase reducedQueryPhase, boolean ignoreFrom, ScoreDoc[] sortedDocs, AtomicArray<? extends QuerySearchResultProvider> fetchResultsArr) {
    List<? extends AtomicArray.Entry<? extends QuerySearchResultProvider>> fetchResults = fetchResultsArr.asList();
    boolean sorted = false;
    int sortScoreIndex = -1;
    if (reducedQueryPhase.oneResult.topDocs() instanceof TopFieldDocs) {
        TopFieldDocs fieldDocs = (TopFieldDocs) reducedQueryPhase.oneResult.queryResult().topDocs();
        if (fieldDocs instanceof CollapseTopFieldDocs && fieldDocs.fields.length == 1 && fieldDocs.fields[0].getType() == SortField.Type.SCORE) {
            sorted = false;
        } else {
            sorted = true;
            for (int i = 0; i < fieldDocs.fields.length; i++) {
                if (fieldDocs.fields[i].getType() == SortField.Type.SCORE) {
                    sortScoreIndex = i;
                }
            }
        }
    }
    // clean the fetch counter
    for (AtomicArray.Entry<? extends QuerySearchResultProvider> entry : fetchResults) {
        entry.value.fetchResult().initCounter();
    }
    int from = ignoreFrom ? 0 : reducedQueryPhase.oneResult.queryResult().from();
    int numSearchHits = (int) Math.min(reducedQueryPhase.fetchHits - from, reducedQueryPhase.oneResult.size());
    // with collapsing we can have more fetch hits than sorted docs
    numSearchHits = Math.min(sortedDocs.length, numSearchHits);
    // merge hits
    List<SearchHit> hits = new ArrayList<>();
    if (!fetchResults.isEmpty()) {
        for (int i = 0; i < numSearchHits; i++) {
            ScoreDoc shardDoc = sortedDocs[i];
            QuerySearchResultProvider fetchResultProvider = fetchResultsArr.get(shardDoc.shardIndex);
            if (fetchResultProvider == null) {
                continue;
            }
            FetchSearchResult fetchResult = fetchResultProvider.fetchResult();
            int index = fetchResult.counterGetAndIncrement();
            if (index < fetchResult.hits().internalHits().length) {
                SearchHit searchHit = fetchResult.hits().internalHits()[index];
                searchHit.score(shardDoc.score);
                searchHit.shard(fetchResult.shardTarget());
                if (sorted) {
                    FieldDoc fieldDoc = (FieldDoc) shardDoc;
                    searchHit.sortValues(fieldDoc.fields, reducedQueryPhase.oneResult.sortValueFormats());
                    if (sortScoreIndex != -1) {
                        searchHit.score(((Number) fieldDoc.fields[sortScoreIndex]).floatValue());
                    }
                }
                hits.add(searchHit);
            }
        }
    }
    return new SearchHits(hits.toArray(new SearchHit[hits.size()]), reducedQueryPhase.totalHits, reducedQueryPhase.maxScore);
}
Also used : AtomicArray(org.elasticsearch.common.util.concurrent.AtomicArray) QuerySearchResultProvider(org.elasticsearch.search.query.QuerySearchResultProvider) SearchHit(org.elasticsearch.search.SearchHit) FieldDoc(org.apache.lucene.search.FieldDoc) FetchSearchResult(org.elasticsearch.search.fetch.FetchSearchResult) ArrayList(java.util.ArrayList) IntArrayList(com.carrotsearch.hppc.IntArrayList) CollapseTopFieldDocs(org.apache.lucene.search.grouping.CollapseTopFieldDocs) TopFieldDocs(org.apache.lucene.search.TopFieldDocs) ScoreDoc(org.apache.lucene.search.ScoreDoc) SearchHits(org.elasticsearch.search.SearchHits) CollapseTopFieldDocs(org.apache.lucene.search.grouping.CollapseTopFieldDocs)

Example 4 with FetchSearchResult

use of org.elasticsearch.search.fetch.FetchSearchResult in project elasticsearch by elastic.

the class SearchPhaseController method merge.

/**
     * Enriches search hits and completion suggestion hits from <code>sortedDocs</code> using <code>fetchResultsArr</code>,
     * merges suggestions, aggregations and profile results
     *
     * Expects sortedDocs to have top search docs across all shards, optionally followed by top suggest docs for each named
     * completion suggestion ordered by suggestion name
     */
public InternalSearchResponse merge(boolean ignoreFrom, ScoreDoc[] sortedDocs, ReducedQueryPhase reducedQueryPhase, AtomicArray<? extends QuerySearchResultProvider> fetchResultsArr) {
    if (reducedQueryPhase.isEmpty()) {
        return InternalSearchResponse.empty();
    }
    List<? extends AtomicArray.Entry<? extends QuerySearchResultProvider>> fetchResults = fetchResultsArr.asList();
    SearchHits hits = getHits(reducedQueryPhase, ignoreFrom, sortedDocs, fetchResultsArr);
    if (reducedQueryPhase.suggest != null) {
        if (!fetchResults.isEmpty()) {
            int currentOffset = hits.getHits().length;
            for (CompletionSuggestion suggestion : reducedQueryPhase.suggest.filter(CompletionSuggestion.class)) {
                final List<CompletionSuggestion.Entry.Option> suggestionOptions = suggestion.getOptions();
                for (int scoreDocIndex = currentOffset; scoreDocIndex < currentOffset + suggestionOptions.size(); scoreDocIndex++) {
                    ScoreDoc shardDoc = sortedDocs[scoreDocIndex];
                    QuerySearchResultProvider searchResultProvider = fetchResultsArr.get(shardDoc.shardIndex);
                    if (searchResultProvider == null) {
                        continue;
                    }
                    FetchSearchResult fetchResult = searchResultProvider.fetchResult();
                    int fetchResultIndex = fetchResult.counterGetAndIncrement();
                    if (fetchResultIndex < fetchResult.hits().internalHits().length) {
                        SearchHit hit = fetchResult.hits().internalHits()[fetchResultIndex];
                        CompletionSuggestion.Entry.Option suggestOption = suggestionOptions.get(scoreDocIndex - currentOffset);
                        hit.score(shardDoc.score);
                        hit.shard(fetchResult.shardTarget());
                        suggestOption.setHit(hit);
                    }
                }
                currentOffset += suggestionOptions.size();
            }
            assert currentOffset == sortedDocs.length : "expected no more score doc slices";
        }
    }
    return reducedQueryPhase.buildResponse(hits);
}
Also used : AtomicArray(org.elasticsearch.common.util.concurrent.AtomicArray) CompletionSuggestion(org.elasticsearch.search.suggest.completion.CompletionSuggestion) QuerySearchResultProvider(org.elasticsearch.search.query.QuerySearchResultProvider) SearchHit(org.elasticsearch.search.SearchHit) FetchSearchResult(org.elasticsearch.search.fetch.FetchSearchResult) ScoreDoc(org.apache.lucene.search.ScoreDoc) Entry(org.elasticsearch.search.suggest.Suggest.Suggestion.Entry) SearchHits(org.elasticsearch.search.SearchHits)

Example 5 with FetchSearchResult

use of org.elasticsearch.search.fetch.FetchSearchResult in project elasticsearch by elastic.

the class FetchSearchPhase method innerRun.

private void innerRun() throws IOException {
    final int numShards = context.getNumShards();
    final boolean isScrollSearch = context.getRequest().scroll() != null;
    ScoreDoc[] sortedShardDocs = searchPhaseController.sortDocs(isScrollSearch, queryResults);
    String scrollId = isScrollSearch ? TransportSearchHelper.buildScrollId(queryResults) : null;
    List<AtomicArray.Entry<QuerySearchResultProvider>> queryResultsAsList = queryResults.asList();
    final SearchPhaseController.ReducedQueryPhase reducedQueryPhase = resultConsumer.reduce();
    final boolean queryAndFetchOptimization = queryResults.length() == 1;
    final Runnable finishPhase = () -> moveToNextPhase(searchPhaseController, sortedShardDocs, scrollId, reducedQueryPhase, queryAndFetchOptimization ? queryResults : fetchResults);
    if (queryAndFetchOptimization) {
        assert queryResults.get(0) == null || queryResults.get(0).fetchResult() != null;
        // query AND fetch optimization
        finishPhase.run();
    } else {
        final IntArrayList[] docIdsToLoad = searchPhaseController.fillDocIdsToLoad(numShards, sortedShardDocs);
        if (sortedShardDocs.length == 0) {
            // no docs to fetch -- sidestep everything and return
            queryResultsAsList.stream().map(e -> e.value.queryResult()).forEach(// we have to release contexts here to free up resources
            this::releaseIrrelevantSearchContext);
            finishPhase.run();
        } else {
            final ScoreDoc[] lastEmittedDocPerShard = isScrollSearch ? searchPhaseController.getLastEmittedDocPerShard(reducedQueryPhase, sortedShardDocs, numShards) : null;
            final CountedCollector<FetchSearchResult> counter = new CountedCollector<>(fetchResults::set, // we count down every shard in the result no matter if we got any results or not
            docIdsToLoad.length, finishPhase, context);
            for (int i = 0; i < docIdsToLoad.length; i++) {
                IntArrayList entry = docIdsToLoad[i];
                QuerySearchResultProvider queryResult = queryResults.get(i);
                if (entry == null) {
                    // no results for this shard ID
                    if (queryResult != null) {
                        // if we got some hits from this shard we have to release the context there
                        // we do this as we go since it will free up resources and passing on the request on the
                        // transport layer is cheap.
                        releaseIrrelevantSearchContext(queryResult.queryResult());
                    }
                    // in any case we count down this result since we don't talk to this shard anymore
                    counter.countDown();
                } else {
                    Transport.Connection connection = context.getConnection(queryResult.shardTarget().getNodeId());
                    ShardFetchSearchRequest fetchSearchRequest = createFetchRequest(queryResult.queryResult().id(), i, entry, lastEmittedDocPerShard);
                    executeFetch(i, queryResult.shardTarget(), counter, fetchSearchRequest, queryResult.queryResult(), connection);
                }
            }
        }
    }
}
Also used : SearchShardTarget(org.elasticsearch.search.SearchShardTarget) InternalSearchResponse(org.elasticsearch.search.internal.InternalSearchResponse) Transport(org.elasticsearch.transport.Transport) ScoreDoc(org.apache.lucene.search.ScoreDoc) AtomicArray(org.elasticsearch.common.util.concurrent.AtomicArray) IOException(java.io.IOException) ShardFetchSearchRequest(org.elasticsearch.search.fetch.ShardFetchSearchRequest) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage) Function(java.util.function.Function) QuerySearchResultProvider(org.elasticsearch.search.query.QuerySearchResultProvider) List(java.util.List) Logger(org.apache.logging.log4j.Logger) FetchSearchResult(org.elasticsearch.search.fetch.FetchSearchResult) QuerySearchResult(org.elasticsearch.search.query.QuerySearchResult) Supplier(org.apache.logging.log4j.util.Supplier) IntArrayList(com.carrotsearch.hppc.IntArrayList) ActionRunnable(org.elasticsearch.action.ActionRunnable) ActionListener(org.elasticsearch.action.ActionListener) QuerySearchResultProvider(org.elasticsearch.search.query.QuerySearchResultProvider) FetchSearchResult(org.elasticsearch.search.fetch.FetchSearchResult) ScoreDoc(org.apache.lucene.search.ScoreDoc) ShardFetchSearchRequest(org.elasticsearch.search.fetch.ShardFetchSearchRequest) ActionRunnable(org.elasticsearch.action.ActionRunnable) IntArrayList(com.carrotsearch.hppc.IntArrayList) Transport(org.elasticsearch.transport.Transport)

Aggregations

ScoreDoc (org.apache.lucene.search.ScoreDoc)13 FetchSearchResult (org.elasticsearch.search.fetch.FetchSearchResult)13 SearchHit (org.elasticsearch.search.SearchHit)11 SearchHits (org.elasticsearch.search.SearchHits)10 QuerySearchResultProvider (org.elasticsearch.search.query.QuerySearchResultProvider)10 IOException (java.io.IOException)9 TopDocs (org.apache.lucene.search.TopDocs)8 QuerySearchResult (org.elasticsearch.search.query.QuerySearchResult)8 SearchShardTarget (org.elasticsearch.search.SearchShardTarget)7 AtomicReference (java.util.concurrent.atomic.AtomicReference)6 ActionListener (org.elasticsearch.action.ActionListener)6 Index (org.elasticsearch.index.Index)6 QueryFetchSearchResult (org.elasticsearch.search.fetch.QueryFetchSearchResult)6 ShardFetchSearchRequest (org.elasticsearch.search.fetch.ShardFetchSearchRequest)6 AtomicArray (org.elasticsearch.common.util.concurrent.AtomicArray)4 IntArrayList (com.carrotsearch.hppc.IntArrayList)3 FieldDoc (org.apache.lucene.search.FieldDoc)3 ArrayList (java.util.ArrayList)2 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)2 CompletionSuggestion (org.elasticsearch.search.suggest.completion.CompletionSuggestion)2