Skip to content

Commit

Permalink
FilterPathBasedFilter support match fieldname with dot (#83178)
Browse files Browse the repository at this point in the history
Current `FilterPathBasedFilter` does not support match fieldName with
dot. This PR merges the changes of #83148 and #83152 together to add the
ability of `matching fieldName with dot` to the `FilterPathBasedFilter`.
  • Loading branch information
mushao999 committed Jan 28, 2022
1 parent 5f98acc commit 2c03af3
Show file tree
Hide file tree
Showing 10 changed files with 515 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public void setup() throws IOException {
);
includesSet = Set.of(fetchContext.includes());
excludesSet = Set.of(fetchContext.excludes());
parserConfig = XContentParserConfiguration.EMPTY.withFiltering(includesSet, excludesSet);
parserConfig = XContentParserConfiguration.EMPTY.withFiltering(includesSet, excludesSet, false);
}

private BytesReference read300BytesExample() throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public class FilterContentBenchmark {
private BytesReference source;
private XContentParserConfiguration parserConfig;
private Set<String> filters;
private XContentParserConfiguration parserConfigMatchDotsInFieldNames;

@Setup
public void setup() throws IOException {
Expand All @@ -72,7 +73,8 @@ public void setup() throws IOException {
};
source = readSource(sourceFile);
filters = buildFilters();
parserConfig = buildParseConfig();
parserConfig = buildParseConfig(false);
parserConfigMatchDotsInFieldNames = buildParseConfig(true);
}

private Set<String> buildFilters() {
Expand Down Expand Up @@ -105,9 +107,14 @@ public BytesReference filterWithParserConfigCreated() throws IOException {
return filter(this.parserConfig);
}

@Benchmark
public BytesReference filterWithParserConfigCreatedMatchDotsInFieldNames() throws IOException {
return filter(this.parserConfigMatchDotsInFieldNames);
}

@Benchmark
public BytesReference filterWithNewParserConfig() throws IOException {
XContentParserConfiguration contentParserConfiguration = buildParseConfig();
XContentParserConfiguration contentParserConfiguration = buildParseConfig(false);
return filter(contentParserConfiguration);
}

Expand Down Expand Up @@ -152,7 +159,7 @@ public BytesReference filterWithBuilder() throws IOException {
}
}

private XContentParserConfiguration buildParseConfig() {
private XContentParserConfiguration buildParseConfig(boolean matchDotsInFieldNames) {
Set<String> includes;
Set<String> excludes;
if (inclusive) {
Expand All @@ -162,7 +169,7 @@ private XContentParserConfiguration buildParseConfig() {
includes = null;
excludes = filters;
}
return XContentParserConfiguration.EMPTY.withFiltering(includes, excludes);
return XContentParserConfiguration.EMPTY.withFiltering(includes, excludes, matchDotsInFieldNames);
}

private BytesReference filter(XContentParserConfiguration contentParserConfiguration) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,34 +32,45 @@ public class XContentParserConfiguration {
DeprecationHandler.THROW_UNSUPPORTED_OPERATION,
RestApiVersion.current(),
null,
null
null,
false
);

final NamedXContentRegistry registry;
final DeprecationHandler deprecationHandler;
final RestApiVersion restApiVersion;
final FilterPath[] includes;
final FilterPath[] excludes;
final boolean filtersMatchFieldNamesWithDots;

private XContentParserConfiguration(
NamedXContentRegistry registry,
DeprecationHandler deprecationHandler,
RestApiVersion restApiVersion,
FilterPath[] includes,
FilterPath[] excludes
FilterPath[] excludes,
boolean filtersMatchFieldNamesWithDots
) {
this.registry = registry;
this.deprecationHandler = deprecationHandler;
this.restApiVersion = restApiVersion;
this.includes = includes;
this.excludes = excludes;
this.filtersMatchFieldNamesWithDots = filtersMatchFieldNamesWithDots;
}

/**
* Replace the registry backing {@link XContentParser#namedObject}.
*/
public XContentParserConfiguration withRegistry(NamedXContentRegistry registry) {
return new XContentParserConfiguration(registry, deprecationHandler, restApiVersion, includes, excludes);
return new XContentParserConfiguration(
registry,
deprecationHandler,
restApiVersion,
includes,
excludes,
filtersMatchFieldNamesWithDots
);
}

public NamedXContentRegistry registry() {
Expand All @@ -71,7 +82,14 @@ public NamedXContentRegistry registry() {
* a deprecated field.
*/
public XContentParserConfiguration withDeprecationHandler(DeprecationHandler deprecationHandler) {
return new XContentParserConfiguration(registry, deprecationHandler, restApiVersion, includes, excludes);
return new XContentParserConfiguration(
registry,
deprecationHandler,
restApiVersion,
includes,
excludes,
filtersMatchFieldNamesWithDots
);
}

public DeprecationHandler deprecationHandler() {
Expand All @@ -83,7 +101,14 @@ public DeprecationHandler deprecationHandler() {
* {@link RestApiVersion}.
*/
public XContentParserConfiguration withRestApiVersion(RestApiVersion restApiVersion) {
return new XContentParserConfiguration(registry, deprecationHandler, restApiVersion, includes, excludes);
return new XContentParserConfiguration(
registry,
deprecationHandler,
restApiVersion,
includes,
excludes,
filtersMatchFieldNamesWithDots
);
}

public RestApiVersion restApiVersion() {
Expand All @@ -93,13 +118,18 @@ public RestApiVersion restApiVersion() {
/**
* Replace the configured filtering.
*/
public XContentParserConfiguration withFiltering(Set<String> includeStrings, Set<String> excludeStrings) {
public XContentParserConfiguration withFiltering(
Set<String> includeStrings,
Set<String> excludeStrings,
boolean filtersMatchFieldNamesWithDots
) {
return new XContentParserConfiguration(
registry,
deprecationHandler,
restApiVersion,
FilterPath.compile(includeStrings),
FilterPath.compile(excludeStrings)
FilterPath.compile(excludeStrings),
filtersMatchFieldNamesWithDots
);
}

Expand All @@ -112,10 +142,20 @@ public JsonParser filter(JsonParser parser) {
throw new UnsupportedOperationException("double wildcards are not supported in filtered excludes");
}
}
filtered = new FilteringParserDelegate(filtered, new FilterPathBasedFilter(excludes, false), true, true);
filtered = new FilteringParserDelegate(
filtered,
new FilterPathBasedFilter(excludes, false, filtersMatchFieldNamesWithDots),
true,
true
);
}
if (includes != null) {
filtered = new FilteringParserDelegate(filtered, new FilterPathBasedFilter(includes, true), true, true);
filtered = new FilteringParserDelegate(
filtered,
new FilterPathBasedFilter(includes, true, filtersMatchFieldNamesWithDots),
true,
true
);
}
return filtered;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,22 @@ private boolean isFinalNode() {
* if current node is a double wildcard node, the node will also add to nextFilters.
* @param name the xcontent property name
* @param nextFilters nextFilters is a List, used to check the inner property of name
* @param matchFieldNamesWithDots support dot in field name or not
* @return true if the name equal a final node, otherwise return false
*/
boolean matches(String name, List<FilterPath> nextFilters) {
boolean matches(String name, List<FilterPath> nextFilters, boolean matchFieldNamesWithDots) {
if (nextFilters == null) {
return false;
}

// match dot first
if (matchFieldNamesWithDots) {
// contains dot and not the first or last char
int dotIndex = name.indexOf('.');
if ((dotIndex != -1) && (dotIndex != 0) && (dotIndex != name.length() - 1)) {
return matchFieldNamesWithDots(name, dotIndex, nextFilters);
}
}
FilterPath termNode = termsChildren.get(name);
if (termNode != null) {
if (termNode.isFinalNode()) {
Expand Down Expand Up @@ -102,6 +111,25 @@ boolean matches(String name, List<FilterPath> nextFilters) {
return false;
}

private boolean matchFieldNamesWithDots(String name, int dotIndex, List<FilterPath> nextFilters) {
String prefixName = name.substring(0, dotIndex);
String suffixName = name.substring(dotIndex + 1);
List<FilterPath> prefixFilterPath = new ArrayList<>();
boolean prefixMatch = matches(prefixName, prefixFilterPath, true);
// if prefixMatch return true(because prefix is a final FilterPath node)
if (prefixMatch) {
return true;
}
// if has prefixNextFilter, use them to match suffix
for (FilterPath filter : prefixFilterPath) {
boolean matches = filter.matches(suffixName, nextFilters, true);
if (matches) {
return true;
}
}
return false;
}

private static class FilterPathBuilder {
private class BuildNode {
private final Map<String, BuildNode> children;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,19 @@ public String toString() {

private final boolean inclusive;

public FilterPathBasedFilter(FilterPath[] filters, boolean inclusive) {
private final boolean matchFieldNamesWithDots;

public FilterPathBasedFilter(FilterPath[] filters, boolean inclusive, boolean matchFieldNamesWithDots) {
if (filters == null || filters.length == 0) {
throw new IllegalArgumentException("filters cannot be null or empty");
}
this.inclusive = inclusive;
this.filters = filters;
this.matchFieldNamesWithDots = matchFieldNamesWithDots;
}

public FilterPathBasedFilter(Set<String> filters, boolean inclusive) {
this(FilterPath.compile(filters), inclusive);
this(FilterPath.compile(filters), inclusive, false);
}

/**
Expand All @@ -61,14 +64,18 @@ private TokenFilter evaluate(String name, FilterPath[] filterPaths) {
if (filterPaths != null) {
List<FilterPath> nextFilters = new ArrayList<>();
for (FilterPath filter : filterPaths) {
boolean matches = filter.matches(name, nextFilters);
boolean matches = filter.matches(name, nextFilters, matchFieldNamesWithDots);
if (matches) {
return MATCHING;
}
}

if (nextFilters.isEmpty() == false) {
return new FilterPathBasedFilter(nextFilters.toArray(new FilterPath[nextFilters.size()]), inclusive);
return new FilterPathBasedFilter(
nextFilters.toArray(new FilterPath[nextFilters.size()]),
inclusive,
matchFieldNamesWithDots
);
}
}
return NO_MATCHING;
Expand Down

0 comments on commit 2c03af3

Please sign in to comment.