org.opensearch.index.query.SourceFieldMatchQuery Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of opensearch Show documentation
Show all versions of opensearch Show documentation
OpenSearch subproject :server
/*
* 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.
*/
package org.opensearch.index.query;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.memory.MemoryIndex;
import org.apache.lucene.search.ConstantScoreScorer;
import org.apache.lucene.search.ConstantScoreWeight;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.QueryVisitor;
import org.apache.lucene.search.ScoreMode;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.TwoPhaseIterator;
import org.apache.lucene.search.Weight;
import org.opensearch.index.mapper.MappedFieldType;
import org.opensearch.index.mapper.SourceValueFetcher;
import org.opensearch.search.lookup.LeafSearchLookup;
import org.opensearch.search.lookup.SearchLookup;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
/**
* A query that matches against each document from the parent query by filtering using the source field values.
* Useful to query against field type which doesn't store positional data and field is not stored/computed dynamically.
*/
public class SourceFieldMatchQuery extends Query {
private final Query delegateQuery;
private final Query filter;
private final SearchLookup lookup;
private final MappedFieldType fieldType;
private final SourceValueFetcher valueFetcher;
private final QueryShardContext context;
/**
* Constructs a SourceFieldMatchQuery.
*
* @param delegateQuery The parent query to use to find matches.
* @param filter The query used to filter further by running against field value fetched using _source field.
* @param fieldType The mapped field type.
* @param context The QueryShardContext to get lookup and valueFetcher
*/
public SourceFieldMatchQuery(Query delegateQuery, Query filter, MappedFieldType fieldType, QueryShardContext context) {
this.delegateQuery = delegateQuery;
this.filter = filter;
this.fieldType = fieldType;
this.context = context;
this.lookup = context.lookup();
if (!context.documentMapper("").sourceMapper().enabled()) {
throw new IllegalArgumentException(
"SourceFieldMatchQuery error: unable to fetch fields from _source field: _source is disabled in the mappings "
+ "for index ["
+ context.index().getName()
+ "]"
);
}
this.valueFetcher = (SourceValueFetcher) fieldType.valueFetcher(context, lookup, null);
}
@Override
public void visit(QueryVisitor visitor) {
delegateQuery.visit(visitor);
}
@Override
public Query rewrite(IndexSearcher indexSearcher) throws IOException {
Query rewritten = delegateQuery.rewrite(indexSearcher);
if (rewritten == delegateQuery) {
return this;
}
return new SourceFieldMatchQuery(rewritten, filter, fieldType, context);
}
@Override
public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
Weight weight = delegateQuery.createWeight(searcher, ScoreMode.TOP_DOCS, boost);
return new ConstantScoreWeight(this, boost) {
@Override
public Scorer scorer(LeafReaderContext context) throws IOException {
Scorer scorer = weight.scorer(context);
if (scorer == null) {
// none of the docs are matching
return null;
}
DocIdSetIterator approximation = scorer.iterator();
LeafSearchLookup leafSearchLookup = lookup.getLeafSearchLookup(context);
TwoPhaseIterator twoPhase = new TwoPhaseIterator(approximation) {
@Override
public boolean matches() {
leafSearchLookup.setDocument(approximation.docID());
List