mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-19 19:35:02 +00:00
optimize single shard search (or search result) by not doing another round of sorting
This commit is contained in:
parent
8c196d8b84
commit
0bce34cb5a
@ -27,7 +27,9 @@ import org.elasticsearch.common.collect.Iterables;
|
|||||||
import org.elasticsearch.common.collect.Lists;
|
import org.elasticsearch.common.collect.Lists;
|
||||||
import org.elasticsearch.common.collect.Maps;
|
import org.elasticsearch.common.collect.Maps;
|
||||||
import org.elasticsearch.common.collect.Ordering;
|
import org.elasticsearch.common.collect.Ordering;
|
||||||
|
import org.elasticsearch.common.component.AbstractComponent;
|
||||||
import org.elasticsearch.common.inject.Inject;
|
import org.elasticsearch.common.inject.Inject;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.trove.ExtTIntArrayList;
|
import org.elasticsearch.common.trove.ExtTIntArrayList;
|
||||||
import org.elasticsearch.common.trove.impl.Constants;
|
import org.elasticsearch.common.trove.impl.Constants;
|
||||||
import org.elasticsearch.common.trove.map.hash.TObjectIntHashMap;
|
import org.elasticsearch.common.trove.map.hash.TObjectIntHashMap;
|
||||||
@ -53,7 +55,7 @@ import java.util.Map;
|
|||||||
/**
|
/**
|
||||||
* @author kimchy (shay.banon)
|
* @author kimchy (shay.banon)
|
||||||
*/
|
*/
|
||||||
public class SearchPhaseController {
|
public class SearchPhaseController extends AbstractComponent {
|
||||||
|
|
||||||
public static Ordering<QuerySearchResultProvider> QUERY_RESULT_ORDERING = new Ordering<QuerySearchResultProvider>() {
|
public static Ordering<QuerySearchResultProvider> QUERY_RESULT_ORDERING = new Ordering<QuerySearchResultProvider>() {
|
||||||
@Override public int compare(@Nullable QuerySearchResultProvider o1, @Nullable QuerySearchResultProvider o2) {
|
@Override public int compare(@Nullable QuerySearchResultProvider o1, @Nullable QuerySearchResultProvider o2) {
|
||||||
@ -69,8 +71,16 @@ public class SearchPhaseController {
|
|||||||
|
|
||||||
private final FacetProcessors facetProcessors;
|
private final FacetProcessors facetProcessors;
|
||||||
|
|
||||||
@Inject public SearchPhaseController(FacetProcessors facetProcessors) {
|
private final boolean optimizeSingleShard;
|
||||||
|
|
||||||
|
@Inject public SearchPhaseController(Settings settings, FacetProcessors facetProcessors) {
|
||||||
|
super(settings);
|
||||||
this.facetProcessors = facetProcessors;
|
this.facetProcessors = facetProcessors;
|
||||||
|
this.optimizeSingleShard = componentSettings.getAsBoolean("optimize_single_shard", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean optimizeSingleShard() {
|
||||||
|
return optimizeSingleShard;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AggregatedDfs aggregateDfs(Iterable<DfsSearchResult> results) {
|
public AggregatedDfs aggregateDfs(Iterable<DfsSearchResult> results) {
|
||||||
@ -90,6 +100,52 @@ public class SearchPhaseController {
|
|||||||
return EMPTY;
|
return EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (optimizeSingleShard) {
|
||||||
|
boolean canOptimize = false;
|
||||||
|
QuerySearchResult result = null;
|
||||||
|
if (results1.size() == 1) {
|
||||||
|
canOptimize = true;
|
||||||
|
result = results1.iterator().next().queryResult();
|
||||||
|
} else {
|
||||||
|
// lets see if we only got hits from a single shard, if so, we can optimize...
|
||||||
|
for (QuerySearchResultProvider queryResult : results1) {
|
||||||
|
if (queryResult.queryResult().topDocs().scoreDocs.length > 0) {
|
||||||
|
if (result != null) { // we already have one, can't really optimize
|
||||||
|
canOptimize = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
canOptimize = true;
|
||||||
|
result = queryResult.queryResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (canOptimize) {
|
||||||
|
ScoreDoc[] scoreDocs = result.topDocs().scoreDocs;
|
||||||
|
if (scoreDocs.length < result.from()) {
|
||||||
|
return EMPTY;
|
||||||
|
}
|
||||||
|
int resultDocsSize = result.size();
|
||||||
|
if ((scoreDocs.length - result.from()) < resultDocsSize) {
|
||||||
|
resultDocsSize = scoreDocs.length - result.from();
|
||||||
|
}
|
||||||
|
if (result.topDocs() instanceof TopFieldDocs) {
|
||||||
|
ShardDoc[] docs = new ShardDoc[resultDocsSize];
|
||||||
|
for (int i = 0; i < resultDocsSize; i++) {
|
||||||
|
ScoreDoc scoreDoc = scoreDocs[result.from() + i];
|
||||||
|
docs[i] = new ShardFieldDoc(result.shardTarget(), scoreDoc.doc, scoreDoc.score, ((FieldDoc) scoreDoc).fields);
|
||||||
|
}
|
||||||
|
return docs;
|
||||||
|
} else {
|
||||||
|
ShardDoc[] docs = new ShardDoc[resultDocsSize];
|
||||||
|
for (int i = 0; i < resultDocsSize; i++) {
|
||||||
|
ScoreDoc scoreDoc = scoreDocs[result.from() + i];
|
||||||
|
docs[i] = new ShardScoreDoc(result.shardTarget(), scoreDoc.doc, scoreDoc.score);
|
||||||
|
}
|
||||||
|
return docs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
List<? extends QuerySearchResultProvider> results = QUERY_RESULT_ORDERING.sortedCopy(results1);
|
List<? extends QuerySearchResultProvider> results = QUERY_RESULT_ORDERING.sortedCopy(results1);
|
||||||
|
|
||||||
QuerySearchResultProvider queryResultProvider = results.get(0);
|
QuerySearchResultProvider queryResultProvider = results.get(0);
|
||||||
|
@ -66,7 +66,12 @@ public class SingleShardEmbeddedSearchTests extends AbstractNodesTests {
|
|||||||
|
|
||||||
private Client client;
|
private Client client;
|
||||||
|
|
||||||
|
protected boolean optimizeSingleShard() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@BeforeClass public void createNodeAndInitWithData() throws Exception {
|
@BeforeClass public void createNodeAndInitWithData() throws Exception {
|
||||||
|
putDefaultSettings(settingsBuilder().put("search.controller.optimize_single_shard", optimizeSingleShard()));
|
||||||
startNode("server1");
|
startNode("server1");
|
||||||
client = client("server1");
|
client = client("server1");
|
||||||
|
|
||||||
@ -89,6 +94,10 @@ public class SingleShardEmbeddedSearchTests extends AbstractNodesTests {
|
|||||||
closeAllNodes();
|
closeAllNodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test public void verifyOptimizeSingleShardSetting() {
|
||||||
|
assertThat(searchPhaseController.optimizeSingleShard(), equalTo(optimizeSingleShard()));
|
||||||
|
}
|
||||||
|
|
||||||
@Test public void testDirectDfs() throws Exception {
|
@Test public void testDirectDfs() throws Exception {
|
||||||
DfsSearchResult dfsResult = searchService.executeDfsPhase(searchRequest(searchSource().query(termQuery("name", "test1"))));
|
DfsSearchResult dfsResult = searchService.executeDfsPhase(searchRequest(searchSource().query(termQuery("name", "test1"))));
|
||||||
|
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to Elastic Search and Shay Banon under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. Elastic Search licenses this
|
||||||
|
* file to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.test.integration.search.embedded;
|
||||||
|
|
||||||
|
public class SingleShardNoOptimizationEmbeddedSearchTests extends SingleShardEmbeddedSearchTests {
|
||||||
|
|
||||||
|
@Override protected boolean optimizeSingleShard() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user