Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FilterFieldType #17627

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* 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.mapper;

import org.opensearch.test.OpenSearchTestCase;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

public class FilterFieldTypeTest extends OpenSearchTestCase {

private static final class MethodSignature {
private final String name;
private final Class<?> returnType;
private final Class<?>[] parameterTypes;

public MethodSignature(String name, Class<?> returnType, Class<?>[] parameterTypes) {
this.name = name;
this.returnType = returnType;
this.parameterTypes = parameterTypes;
}

@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
MethodSignature that = (MethodSignature) o;
return Objects.equals(name, that.name)
&& Objects.equals(returnType, that.returnType)
&& Objects.deepEquals(parameterTypes, that.parameterTypes);
}

@Override
public int hashCode() {
return Objects.hash(name, returnType, Arrays.hashCode(parameterTypes));
}
}

private static final Set<MethodSignature> EXCLUDED_SIGNATURES = Set.of(new MethodSignature("typeName", String.class, new Class<?>[0]));

public void testAllMethodsDelegated() {
Method[] mappedFieldTypeMethods = MappedFieldType.class.getMethods();
Method[] filterFieldTypeMethods = FilterFieldType.class.getMethods();

Set<MethodSignature> mappedFieldTypeMethodSignatures = new HashSet<>();
for (Method method : mappedFieldTypeMethods) {
if (method.getDeclaringClass() == MappedFieldType.class
&& Modifier.isFinal(method.getModifiers()) == false
&& Modifier.isStatic(method.getModifiers()) == false) {
mappedFieldTypeMethodSignatures.add(
new MethodSignature(method.getName(), method.getReturnType(), method.getParameterTypes())
);
}
}

Set<MethodSignature> filterFieldTypeMethodSignatures = new HashSet<>();
for (Method method : filterFieldTypeMethods) {
if (method.getDeclaringClass() == FilterFieldType.class) {
filterFieldTypeMethodSignatures.add(
new MethodSignature(method.getName(), method.getReturnType(), method.getParameterTypes())
);
}
}
for (MethodSignature methodSignature : mappedFieldTypeMethodSignatures) {
if (filterFieldTypeMethodSignatures.contains(methodSignature)) {
assertFalse(
"Method " + methodSignature.name + " should NOT be implemented in " + FilterFieldType.class.getSimpleName(),
EXCLUDED_SIGNATURES.contains(methodSignature)
);
} else {
assertTrue(
"Method " + methodSignature.name + " should be implemented in " + FilterFieldType.class.getSimpleName(),
EXCLUDED_SIGNATURES.contains(methodSignature)
);
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
/*
* 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.mapper;

import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queries.intervals.IntervalsSource;
import org.apache.lucene.queries.spans.SpanMultiTermQueryWrapper;
import org.apache.lucene.queries.spans.SpanQuery;
import org.apache.lucene.search.MultiTermQuery;
import org.apache.lucene.search.Query;
import org.opensearch.common.geo.ShapeRelation;
import org.opensearch.common.time.DateMathParser;
import org.opensearch.common.unit.Fuzziness;
import org.opensearch.index.analysis.NamedAnalyzer;
import org.opensearch.index.fielddata.IndexFieldData;
import org.opensearch.index.query.IntervalMode;
import org.opensearch.index.query.QueryRewriteContext;
import org.opensearch.index.query.QueryShardContext;
import org.opensearch.search.DocValueFormat;
import org.opensearch.search.lookup.SearchLookup;

import java.io.IOException;
import java.time.ZoneId;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;

public abstract class FilterFieldType<T extends MappedFieldType> extends MappedFieldType {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add java docs on this class, with some examples on how to use it. This is a good addition in core.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we annotate this with @publicapi?

protected final T delegate;

public FilterFieldType(T delegate) {
super(
delegate.name(),
delegate.isSearchable(),
delegate.isStored(),
delegate.hasDocValues(),
delegate.getTextSearchInfo(),
delegate.meta()
);
this.delegate = delegate;
}

@Override
public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
return delegate.valueFetcher(context, searchLookup, format);
}

@Override
public Query termQuery(Object value, QueryShardContext context) {
return delegate.termQuery(value, context);
}

@Override
public String familyTypeName() {
return delegate.familyTypeName();
}

@Override
public String name() {
return delegate.name();
}

@Override
public float boost() {
return delegate.boost();
}

@Override
public void setBoost(float boost) {
delegate.setBoost(boost);
}

@Override
public boolean hasDocValues() {
return delegate.hasDocValues();
}

@Override
public NamedAnalyzer indexAnalyzer() {
return delegate.indexAnalyzer();
}

@Override
public void setIndexAnalyzer(NamedAnalyzer analyzer) {
delegate.setIndexAnalyzer(analyzer);
}

@Override
public Object valueForDisplay(Object value) {
return delegate.valueForDisplay(value);
}

@Override
public boolean isSearchable() {
return delegate.isSearchable();
}

@Override
public boolean isStored() {
return delegate.isStored();
}

@Override
public Function<byte[], Number> pointReaderIfPossible() {
return delegate.pointReaderIfPossible();
}

@Override
public boolean isAggregatable() {
return delegate.isAggregatable();
}

@Override
public Query termQueryCaseInsensitive(Object value, QueryShardContext context) {
return delegate.termQueryCaseInsensitive(value, context);
}

@Override
public Query termsQuery(List<?> values, QueryShardContext context) {
return delegate.termsQuery(values, context);
}

@Override
public Query rangeQuery(
Object lowerTerm,
Object upperTerm,
boolean includeLower,
boolean includeUpper,
ShapeRelation relation,
ZoneId timeZone,
DateMathParser parser,
QueryShardContext context
) {
return delegate.rangeQuery(lowerTerm, upperTerm, includeLower, includeUpper, relation, timeZone, parser, context);
}

@Override
public Query fuzzyQuery(
Object value,
Fuzziness fuzziness,
int prefixLength,
int maxExpansions,
boolean transpositions,
MultiTermQuery.RewriteMethod method,
QueryShardContext context
) {
return delegate.fuzzyQuery(value, fuzziness, prefixLength, maxExpansions, transpositions, method, context);
}

@Override
public Query prefixQuery(String value, MultiTermQuery.RewriteMethod method, boolean caseInsensitve, QueryShardContext context) {
return delegate.prefixQuery(value, method, caseInsensitve, context);
}

@Override
public Query wildcardQuery(String value, MultiTermQuery.RewriteMethod method, boolean caseInsensitve, QueryShardContext context) {
return delegate.wildcardQuery(value, method, caseInsensitve, context);
}

@Override
public Query normalizedWildcardQuery(String value, MultiTermQuery.RewriteMethod method, QueryShardContext context) {
return delegate.normalizedWildcardQuery(value, method, context);
}

@Override
public Query regexpQuery(
String value,
int syntaxFlags,
int matchFlags,
int maxDeterminizedStates,
MultiTermQuery.RewriteMethod method,
QueryShardContext context
) {
return delegate.regexpQuery(value, syntaxFlags, matchFlags, maxDeterminizedStates, method, context);
}

@Override
public Query existsQuery(QueryShardContext context) {
return delegate.existsQuery(context);
}

@Override
public Query phraseQuery(TokenStream stream, int slop, boolean enablePositionIncrements) throws IOException {
return delegate.phraseQuery(stream, slop, enablePositionIncrements);
}

@Override
public Query phraseQuery(TokenStream stream, int slop, boolean enablePositionIncrements, QueryShardContext context) throws IOException {
return delegate.phraseQuery(stream, slop, enablePositionIncrements, context);
}

@Override
public Query multiPhraseQuery(TokenStream stream, int slop, boolean enablePositionIncrements) throws IOException {
return delegate.multiPhraseQuery(stream, slop, enablePositionIncrements);
}

@Override
public Query multiPhraseQuery(TokenStream stream, int slop, boolean enablePositionIncrements, QueryShardContext context)
throws IOException {
return delegate.multiPhraseQuery(stream, slop, enablePositionIncrements, context);
}

@Override
public Query phrasePrefixQuery(TokenStream stream, int slop, int maxExpansions) throws IOException {
return delegate.phrasePrefixQuery(stream, slop, maxExpansions);
}

@Override
public Query phrasePrefixQuery(TokenStream stream, int slop, int maxExpansions, QueryShardContext context) throws IOException {
return delegate.phrasePrefixQuery(stream, slop, maxExpansions, context);
}

@Override
public SpanQuery spanPrefixQuery(String value, SpanMultiTermQueryWrapper.SpanRewriteMethod method, QueryShardContext context) {
return delegate.spanPrefixQuery(value, method, context);
}

@Override
public Query distanceFeatureQuery(Object origin, String pivot, float boost, QueryShardContext context) {
return delegate.distanceFeatureQuery(origin, pivot, boost, context);
}

@Override
public IntervalsSource intervals(String query, int max_gaps, IntervalMode mode, NamedAnalyzer analyzer, boolean prefix)
throws IOException {
return delegate.intervals(query, max_gaps, mode, analyzer, prefix);
}

@Override
public Relation isFieldWithinQuery(
IndexReader reader,
Object from,
Object to,
boolean includeLower,
boolean includeUpper,
ZoneId timeZone,
DateMathParser dateMathParser,
QueryRewriteContext context
) throws IOException {
return delegate.isFieldWithinQuery(reader, from, to, includeLower, includeUpper, timeZone, dateMathParser, context);
}

@Override
public boolean eagerGlobalOrdinals() {
return delegate.eagerGlobalOrdinals();
}

@Override
public void setEagerGlobalOrdinals(boolean eagerGlobalOrdinals) {
delegate.setEagerGlobalOrdinals(eagerGlobalOrdinals);
}

@Override
public DocValueFormat docValueFormat(String format, ZoneId timeZone) {
return delegate.docValueFormat(format, timeZone);
}

@Override
public Map<String, String> meta() {
return delegate.meta();
}

@Override
public TextSearchInfo getTextSearchInfo() {
return delegate.getTextSearchInfo();
}

@Override
public IndexFieldData.Builder fielddataBuilder(String fullyQualifiedIndexName, Supplier<SearchLookup> searchLookup) {
return delegate.fielddataBuilder(fullyQualifiedIndexName, searchLookup);
}

@Override
public MappedFieldType unwrap() {
return delegate.unwrap();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -521,4 +521,12 @@ public Map<String, String> meta() {
public TextSearchInfo getTextSearchInfo() {
return textSearchInfo;
}

/**
* @return a concrete (unfiltered) field type, which should be the current instance
* if this is not a field type wrapper. See {@link FilterFieldType}.
*/
public MappedFieldType unwrap() {
return this;
}
}
Loading