forked from opensearch-project/OpenSearch
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSearchContext.java
529 lines (401 loc) · 18.5 KB
/
SearchContext.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch 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.
*/
/*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/
package org.opensearch.search.internal;
import org.apache.lucene.search.Collector;
import org.apache.lucene.search.CollectorManager;
import org.apache.lucene.search.FieldDoc;
import org.apache.lucene.search.Query;
import org.opensearch.action.search.SearchShardTask;
import org.opensearch.action.search.SearchType;
import org.opensearch.common.Nullable;
import org.opensearch.common.annotation.PublicApi;
import org.opensearch.common.lease.Releasable;
import org.opensearch.common.lease.Releasables;
import org.opensearch.common.unit.TimeValue;
import org.opensearch.common.util.BigArrays;
import org.opensearch.index.cache.bitset.BitsetFilterCache;
import org.opensearch.index.mapper.MappedFieldType;
import org.opensearch.index.mapper.MapperService;
import org.opensearch.index.mapper.ObjectMapper;
import org.opensearch.index.query.ParsedQuery;
import org.opensearch.index.query.QueryShardContext;
import org.opensearch.index.shard.IndexShard;
import org.opensearch.index.similarity.SimilarityService;
import org.opensearch.search.RescoreDocIds;
import org.opensearch.search.SearchExtBuilder;
import org.opensearch.search.SearchShardTarget;
import org.opensearch.search.aggregations.Aggregator;
import org.opensearch.search.aggregations.BucketCollectorProcessor;
import org.opensearch.search.aggregations.InternalAggregation;
import org.opensearch.search.aggregations.SearchContextAggregations;
import org.opensearch.search.aggregations.bucket.LocalBucketCountThresholds;
import org.opensearch.search.aggregations.bucket.terms.TermsAggregator;
import org.opensearch.search.collapse.CollapseContext;
import org.opensearch.search.dfs.DfsSearchResult;
import org.opensearch.search.fetch.FetchPhase;
import org.opensearch.search.fetch.FetchSearchResult;
import org.opensearch.search.fetch.StoredFieldsContext;
import org.opensearch.search.fetch.subphase.FetchDocValuesContext;
import org.opensearch.search.fetch.subphase.FetchFieldsContext;
import org.opensearch.search.fetch.subphase.FetchSourceContext;
import org.opensearch.search.fetch.subphase.InnerHitsContext;
import org.opensearch.search.fetch.subphase.ScriptFieldsContext;
import org.opensearch.search.fetch.subphase.highlight.SearchHighlightContext;
import org.opensearch.search.profile.Profilers;
import org.opensearch.search.query.QuerySearchResult;
import org.opensearch.search.query.ReduceableSearchResult;
import org.opensearch.search.rescore.RescoreContext;
import org.opensearch.search.sort.SortAndFormats;
import org.opensearch.search.suggest.SuggestionSearchContext;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* This class encapsulates the state needed to execute a search. It holds a reference to the
* shards point in time snapshot (IndexReader / ContextIndexSearcher) and allows passing on
* state from one query / fetch phase to another.
*
* @opensearch.api
*/
@PublicApi(since = "1.0.0")
public abstract class SearchContext implements Releasable {
public static final int DEFAULT_TERMINATE_AFTER = 0;
public static final int TRACK_TOTAL_HITS_ACCURATE = Integer.MAX_VALUE;
public static final int TRACK_TOTAL_HITS_DISABLED = -1;
public static final int DEFAULT_TRACK_TOTAL_HITS_UP_TO = 10000;
// no-op bucket collector processor
public static final BucketCollectorProcessor NO_OP_BUCKET_COLLECTOR_PROCESSOR = new BucketCollectorProcessor() {
@Override
public void processPostCollection(Collector collectorTree) {
// do nothing as there is no aggregation collector
}
@Override
public List<Aggregator> toAggregators(Collection<Collector> collectors) {
// should not be called when there is no aggregation collector
throw new IllegalStateException("Unexpected toAggregators call on NO_OP_BUCKET_COLLECTOR_PROCESSOR");
}
@Override
public List<InternalAggregation> toInternalAggregations(Collection<Collector> collectors) {
// should not be called when there is no aggregation collector
throw new IllegalStateException("Unexpected toInternalAggregations call on NO_OP_BUCKET_COLLECTOR_PROCESSOR");
}
};
private final List<Releasable> releasables = new CopyOnWriteArrayList<>();
private final AtomicBoolean closed = new AtomicBoolean(false);
private InnerHitsContext innerHitsContext;
private volatile boolean searchTimedOut;
protected SearchContext() {}
public abstract void setTask(SearchShardTask task);
public abstract SearchShardTask getTask();
public abstract boolean isCancelled();
public boolean isSearchTimedOut() {
return this.searchTimedOut;
}
public void setSearchTimedOut(boolean searchTimedOut) {
this.searchTimedOut = searchTimedOut;
}
@Override
public final void close() {
if (closed.compareAndSet(false, true)) {
try {
Releasables.close(releasables);
} finally {
doClose();
}
}
}
protected abstract void doClose();
/**
* Should be called before executing the main query and after all other parameters have been set.
* @param rewrite if the set query should be rewritten against the searcher returned from {@link #searcher()}
*/
public abstract void preProcess(boolean rewrite);
/** Automatically apply all required filters to the given query such as
* alias filters, types filters, etc. */
public abstract Query buildFilteredQuery(Query query);
public abstract ShardSearchContextId id();
public abstract String source();
public abstract ShardSearchRequest request();
public abstract SearchType searchType();
public abstract SearchShardTarget shardTarget();
public abstract int numberOfShards();
public abstract float queryBoost();
public abstract ScrollContext scrollContext();
public abstract SearchContextAggregations aggregations();
public abstract SearchContext aggregations(SearchContextAggregations aggregations);
public abstract void addSearchExt(SearchExtBuilder searchExtBuilder);
public abstract SearchExtBuilder getSearchExt(String name);
public abstract SearchHighlightContext highlight();
public abstract void highlight(SearchHighlightContext highlight);
public boolean hasInnerHits() {
return innerHitsContext != null;
}
public InnerHitsContext innerHits() {
if (innerHitsContext == null) {
innerHitsContext = new InnerHitsContext();
}
return innerHitsContext;
}
public abstract SuggestionSearchContext suggest();
public abstract void suggest(SuggestionSearchContext suggest);
/**
* @return list of all rescore contexts. empty if there aren't any.
*/
public abstract List<RescoreContext> rescore();
public abstract void addRescore(RescoreContext rescore);
public final RescoreDocIds rescoreDocIds() {
final List<RescoreContext> rescore = rescore();
if (rescore == null) {
return RescoreDocIds.EMPTY;
}
Map<Integer, Set<Integer>> rescoreDocIds = null;
for (int i = 0; i < rescore.size(); i++) {
final Set<Integer> docIds = rescore.get(i).getRescoredDocs();
if (docIds != null && docIds.isEmpty() == false) {
if (rescoreDocIds == null) {
rescoreDocIds = new HashMap<>();
}
rescoreDocIds.put(i, docIds);
}
}
return rescoreDocIds == null ? RescoreDocIds.EMPTY : new RescoreDocIds(rescoreDocIds);
}
public final void assignRescoreDocIds(RescoreDocIds rescoreDocIds) {
final List<RescoreContext> rescore = rescore();
if (rescore != null) {
for (int i = 0; i < rescore.size(); i++) {
final Set<Integer> docIds = rescoreDocIds.getId(i);
if (docIds != null) {
rescore.get(i).setRescoredDocs(docIds);
}
}
}
}
public abstract boolean hasScriptFields();
public abstract ScriptFieldsContext scriptFields();
/**
* A shortcut function to see whether there is a fetchSourceContext and it says the source is requested.
*/
public abstract boolean sourceRequested();
public abstract boolean hasFetchSourceContext();
public abstract FetchSourceContext fetchSourceContext();
public abstract SearchContext fetchSourceContext(FetchSourceContext fetchSourceContext);
public abstract FetchDocValuesContext docValuesContext();
public abstract SearchContext docValuesContext(FetchDocValuesContext docValuesContext);
/**
* The context related to retrieving fields.
*/
public abstract FetchFieldsContext fetchFieldsContext();
/**
* Sets the context related to retrieving fields.
*/
public abstract SearchContext fetchFieldsContext(FetchFieldsContext fetchFieldsContext);
public abstract ContextIndexSearcher searcher();
public abstract IndexShard indexShard();
public abstract MapperService mapperService();
public abstract SimilarityService similarityService();
public abstract BigArrays bigArrays();
public abstract BitsetFilterCache bitsetFilterCache();
public abstract TimeValue timeout();
public abstract void timeout(TimeValue timeout);
public abstract int terminateAfter();
public abstract void terminateAfter(int terminateAfter);
/**
* Indicates if the current index should perform frequent low level search cancellation check.
* <p>
* Enabling low-level checks will make long running searches to react to the cancellation request faster. However,
* since it will produce more cancellation checks it might slow the search performance down.
*/
public abstract boolean lowLevelCancellation();
public abstract SearchContext minimumScore(float minimumScore);
public abstract Float minimumScore();
public abstract SearchContext sort(SortAndFormats sort);
public abstract SortAndFormats sort();
public abstract SearchContext trackScores(boolean trackScores);
public abstract boolean trackScores();
/**
* Determines whether named queries' scores should be included in the search results.
* By default, this is set to return false, indicating that scores from named queries are not included.
*
* @param includeNamedQueriesScore true to include scores from named queries, false otherwise.
*/
public SearchContext includeNamedQueriesScore(boolean includeNamedQueriesScore) {
// Default implementation does nothing and returns this for chaining.
// Implementations of SearchContext should override this method to actually store the value.
return this;
}
/**
* Checks if scores from named queries are included in the search results.
*
* @return true if scores from named queries are included, false otherwise.
*/
public boolean includeNamedQueriesScore() {
// Default implementation returns false.
// Implementations of SearchContext should override this method to return the actual value.
return false;
}
public abstract SearchContext trackTotalHitsUpTo(int trackTotalHits);
/**
* Indicates the total number of hits to count accurately.
* Defaults to {@link #DEFAULT_TRACK_TOTAL_HITS_UP_TO}.
*/
public abstract int trackTotalHitsUpTo();
public abstract SearchContext searchAfter(FieldDoc searchAfter);
public abstract FieldDoc searchAfter();
public abstract SearchContext collapse(CollapseContext collapse);
public abstract CollapseContext collapse();
public abstract SearchContext parsedPostFilter(ParsedQuery postFilter);
public abstract ParsedQuery parsedPostFilter();
public abstract Query aliasFilter();
public abstract SearchContext parsedQuery(ParsedQuery query);
public abstract ParsedQuery parsedQuery();
/**
* The query to execute, might be rewritten.
*/
public abstract Query query();
public abstract int from();
public abstract SearchContext from(int from);
public abstract int size();
public abstract SearchContext size(int size);
public abstract boolean hasStoredFields();
public abstract boolean hasStoredFieldsContext();
/**
* A shortcut function to see whether there is a storedFieldsContext and it says the fields are requested.
*/
public abstract boolean storedFieldsRequested();
public abstract StoredFieldsContext storedFieldsContext();
public abstract SearchContext storedFieldsContext(StoredFieldsContext storedFieldsContext);
public abstract boolean explain();
public abstract void explain(boolean explain);
@Nullable
public abstract List<String> groupStats();
public abstract void groupStats(List<String> groupStats);
public abstract boolean version();
public abstract void version(boolean version);
/** indicates whether the sequence number and primary term of the last modification to each hit should be returned */
public abstract boolean seqNoAndPrimaryTerm();
/** controls whether the sequence number and primary term of the last modification to each hit should be returned */
public abstract void seqNoAndPrimaryTerm(boolean seqNoAndPrimaryTerm);
public abstract int[] docIdsToLoad();
public abstract int docIdsToLoadFrom();
public abstract int docIdsToLoadSize();
public abstract SearchContext docIdsToLoad(int[] docIdsToLoad, int docsIdsToLoadFrom, int docsIdsToLoadSize);
public abstract DfsSearchResult dfsResult();
public abstract QuerySearchResult queryResult();
public abstract FetchPhase fetchPhase();
public abstract FetchSearchResult fetchResult();
/**
* Return a handle over the profilers for the current search request, or {@code null} if profiling is not enabled.
*/
public abstract Profilers getProfilers();
/**
* Returns concurrent segment search status for the search context
*/
public boolean shouldUseConcurrentSearch() {
return false;
}
/**
* Returns local bucket count thresholds based on concurrent segment search status
*/
public LocalBucketCountThresholds asLocalBucketCountThresholds(TermsAggregator.BucketCountThresholds bucketCountThresholds) {
return new LocalBucketCountThresholds(
shouldUseConcurrentSearch() ? 0 : bucketCountThresholds.getShardMinDocCount(),
bucketCountThresholds.getShardSize()
);
}
/**
* Adds a releasable that will be freed when this context is closed.
*/
public void addReleasable(Releasable releasable) {
releasables.add(releasable);
}
/**
* @return true if the request contains only suggest
*/
public final boolean hasOnlySuggest() {
return request().source() != null && request().source().isSuggestOnly();
}
/**
* Given the full name of a field, returns its {@link MappedFieldType}.
*/
public abstract MappedFieldType fieldType(String name);
public abstract ObjectMapper getObjectMapper(String name);
/**
* Returns time in milliseconds that can be used for relative time calculations.
* WARN: This is not the epoch time and can be a cached time.
*/
public abstract long getRelativeTimeInMillis();
/**
* Returns time in milliseconds that can be used for relative time calculations. this method will fall back to
* {@link SearchContext#getRelativeTimeInMillis()} (which might be a cached time) if useCache was set to true else it will be just be a
* wrapper of {@link System#nanoTime()} converted to milliseconds.
* @param useCache to allow using cached time if true or forcing calling {@link System#nanoTime()} if false
* @return Returns time in milliseconds that can be used for relative time calculations.
*/
public long getRelativeTimeInMillis(boolean useCache) {
if (useCache) {
return getRelativeTimeInMillis();
}
return TimeValue.nsecToMSec(System.nanoTime());
}
/** Return a view of the additional query collector managers that should be run for this context. */
public abstract Map<Class<?>, CollectorManager<? extends Collector, ReduceableSearchResult>> queryCollectorManagers();
public abstract QueryShardContext getQueryShardContext();
@Override
public String toString() {
StringBuilder result = new StringBuilder().append(shardTarget());
if (searchType() != SearchType.DEFAULT) {
result.append("searchType=[").append(searchType()).append("]");
}
if (scrollContext() != null) {
if (scrollContext().scroll != null) {
result.append("scroll=[").append(scrollContext().scroll.keepAlive()).append("]");
} else {
result.append("scroll=[null]");
}
}
result.append(" query=[").append(query()).append("]");
return result.toString();
}
public abstract ReaderContext readerContext();
public abstract InternalAggregation.ReduceContext partialOnShard();
// processor used for bucket collectors
public abstract void setBucketCollectorProcessor(BucketCollectorProcessor bucketCollectorProcessor);
public abstract BucketCollectorProcessor bucketCollectorProcessor();
public abstract boolean shouldUseTimeSeriesDescSortOptimization();
public abstract int getTargetMaxSliceCount();
public int maxAggRewriteFilters() {
return 0;
}
}