Skip to content

Commit a8b232e

Browse files
committed
Change
1 parent 0ca1f56 commit a8b232e

File tree

4 files changed

+144
-131
lines changed

4 files changed

+144
-131
lines changed

libs/x-content/src/main/java/org/elasticsearch/xcontent/support/MapXContentParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ public CharBuffer charBuffer() throws IOException {
160160

161161
@Override
162162
public Object objectText() throws IOException {
163-
throw new UnsupportedOperationException("use text() instead");
163+
return iterator.currentValue();
164164
}
165165

166166
@Override

server/src/main/java/org/elasticsearch/cluster/routing/IndexRouting.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,17 @@
2323
import org.elasticsearch.common.bytes.BytesReference;
2424
import org.elasticsearch.common.regex.Regex;
2525
import org.elasticsearch.common.util.ByteUtils;
26+
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
2627
import org.elasticsearch.common.xcontent.XContentHelper;
28+
import org.elasticsearch.common.xcontent.support.XContentParserFilter;
2729
import org.elasticsearch.core.Nullable;
2830
import org.elasticsearch.features.NodeFeature;
2931
import org.elasticsearch.index.IndexMode;
3032
import org.elasticsearch.index.IndexVersion;
3133
import org.elasticsearch.index.IndexVersions;
3234
import org.elasticsearch.index.mapper.TimeSeriesRoutingHashFieldMapper;
3335
import org.elasticsearch.ingest.ESONIndexed;
34-
import org.elasticsearch.search.lookup.Source;
35-
import org.elasticsearch.search.lookup.SourceFilter;
36+
import org.elasticsearch.ingest.ESONXContentParser;
3637
import org.elasticsearch.transport.Transports;
3738
import org.elasticsearch.xcontent.DeprecationHandler;
3839
import org.elasticsearch.xcontent.NamedXContentRegistry;
@@ -51,6 +52,7 @@
5152
import java.util.Map;
5253
import java.util.OptionalInt;
5354
import java.util.Set;
55+
import java.util.function.Function;
5456
import java.util.function.IntConsumer;
5557
import java.util.function.IntSupplier;
5658
import java.util.function.Predicate;
@@ -314,7 +316,7 @@ public static class ExtractFromSource extends IndexRouting {
314316
private final IndexMode indexMode;
315317
private final boolean trackTimeSeriesRoutingHash;
316318
private final boolean addIdWithRoutingHash;
317-
private final SourceFilter sourceFilter;
319+
private final Function<XContentParser, Map<String, Object>> parserFilter;
318320
private int hash = Integer.MAX_VALUE;
319321

320322
ExtractFromSource(IndexMetadata metadata) {
@@ -329,7 +331,7 @@ public static class ExtractFromSource extends IndexRouting {
329331
List<String> routingPaths = metadata.getRoutingPaths();
330332
isRoutingPath = Regex.simpleMatcher(routingPaths.toArray(String[]::new));
331333
this.parserConfig = XContentParserConfiguration.EMPTY.withFiltering(null, Set.copyOf(routingPaths), null, true);
332-
sourceFilter = new SourceFilter(routingPaths.toArray(new String[0]), Strings.EMPTY_ARRAY);
334+
parserFilter = XContentParserFilter.filter(routingPaths.toArray(new String[0]));
333335
}
334336

335337
public boolean matchesField(String fieldName) {
@@ -361,12 +363,17 @@ public int indexShard(String id, @Nullable String routing, XContentType sourceTy
361363
public int indexShard(String id, @Nullable String routing, XContentType sourceType, ESONIndexed.ESONObject structuredSource) {
362364
assert Transports.assertNotTransportThread("parsing the _source can get slow");
363365
checkNoRouting(routing);
364-
Source source = Source.fromMap(structuredSource, sourceType).filter(sourceFilter);
365366
try (
367+
ESONXContentParser esonxContentParser = new ESONXContentParser(
368+
structuredSource.esonFlat(),
369+
NamedXContentRegistry.EMPTY,
370+
LoggingDeprecationHandler.IGNORE_DEPRECATIONS,
371+
sourceType
372+
);
366373
XContentParser parser = new MapXContentParser(
367374
NamedXContentRegistry.EMPTY,
368375
DeprecationHandler.IGNORE_DEPRECATIONS,
369-
source.source(),
376+
parserFilter.apply(esonxContentParser),
370377
sourceType
371378
)
372379
) {

server/src/main/java/org/elasticsearch/common/xcontent/support/XContentParserFilter.java

Lines changed: 49 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import org.apache.lucene.util.automaton.CharacterRunAutomaton;
1515
import org.apache.lucene.util.automaton.Operations;
1616
import org.elasticsearch.common.regex.Regex;
17-
import org.elasticsearch.ingest.ESONIndexed;
1817
import org.elasticsearch.xcontent.XContentParser;
1918

2019
import java.io.IOException;
@@ -29,23 +28,31 @@ public class XContentParserFilter {
2928

3029
private static final int MAX_DETERMINIZED_STATES = 50_000;
3130

32-
public static Map<String, Object> filter(Map<String, Object> map, String[] includes, String[] excludes) {
33-
return filter(includes, excludes).apply(map);
31+
public static Map<String, Object> filter(XContentParser parser, String[] includes) {
32+
return filter(includes).apply(parser);
3433
}
3534

3635
/**
3736
* Returns a function that filters a document map based on the given include and exclude rules.
38-
* @see #filter(Map, String[], String[]) for details
37+
* @see #filter(XContentParser, String[]) for details
3938
*/
40-
public static Function<Map<String, Object>, Map<String, Object>> filter(String[] includes, String[] excludes) {
39+
public static Function<XContentParser, Map<String, Object>> filter(String[] includes) {
4140
CharacterRunAutomaton matchAllAutomaton = new CharacterRunAutomaton(Automata.makeAnyString());
4241
CharacterRunAutomaton include = compileAutomaton(includes, matchAllAutomaton);
43-
CharacterRunAutomaton exclude = compileAutomaton(excludes, new CharacterRunAutomaton(Automata.makeEmpty()));
4442

4543
// NOTE: We cannot use Operations.minus because of the special case that
4644
// we want all sub properties to match as soon as an object matches
4745

48-
return (map) -> filter((XContentParser) null, include, 0, exclude, 0, matchAllAutomaton);
46+
return (parser) -> {
47+
XContentParser.Token startObjectToken;
48+
try {
49+
startObjectToken = parser.nextToken();
50+
assert startObjectToken == XContentParser.Token.START_OBJECT;
51+
return filter(parser, include, 0, matchAllAutomaton);
52+
} catch (IOException e) {
53+
throw new UncheckedIOException(e);
54+
}
55+
};
4956
}
5057

5158
public static CharacterRunAutomaton compileAutomaton(String[] patterns, CharacterRunAutomaton defaultValue) {
@@ -83,168 +90,86 @@ private static Map<String, Object> filter(
8390
XContentParser parser,
8491
CharacterRunAutomaton includeAutomaton,
8592
int initialIncludeState,
86-
CharacterRunAutomaton excludeAutomaton,
87-
int initialExcludeState,
8893
CharacterRunAutomaton matchAllAutomaton
89-
) {
94+
) throws IOException {
9095
Map<String, Object> filtered = new HashMap<>();
91-
try {
92-
XContentParser.Token startObjectToken = parser.nextToken();
93-
assert startObjectToken == XContentParser.Token.START_OBJECT;
94-
XContentParser.Token token = parser.nextToken();
95-
while (true) {
96-
if (token == XContentParser.Token.END_OBJECT) {
97-
return filtered;
98-
}
99-
100-
token = parser.nextToken();
101-
assert token == XContentParser.Token.FIELD_NAME;
102-
String key = parser.currentName();
103-
token = parser.nextToken();
104-
int includeState = step(includeAutomaton, key, initialIncludeState);
105-
if (includeState == -1) {
106-
parser.skipChildren();
107-
continue;
108-
}
109-
110-
break;
111-
}
112-
} catch (IOException e) {
113-
throw new UncheckedIOException(e);
114-
}
115-
ESONIndexed.ESONObject map = null;
116-
for (Map.Entry<String, ?> entry : map.entrySet()) {
117-
String key = entry.getKey();
96+
XContentParser.Token token;
97+
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
11898

99+
assert token == XContentParser.Token.FIELD_NAME;
100+
String key = parser.currentName();
101+
// Now value token
102+
token = parser.nextToken();
119103
int includeState = step(includeAutomaton, key, initialIncludeState);
120104
if (includeState == -1) {
105+
parser.skipChildren();
121106
continue;
122107
}
123108

124-
int excludeState = step(excludeAutomaton, key, initialExcludeState);
125-
if (excludeState != -1 && excludeAutomaton.isAccept(excludeState)) {
126-
continue;
127-
}
128-
129-
Object value;
130-
if (entry instanceof ESONIndexed.ESONObject.LazyEntry lazyEntry && lazyEntry.isUTF8Bytes()) {
131-
value = lazyEntry.utf8Bytes();
132-
} else {
133-
value = entry.getValue();
134-
}
135-
136109
CharacterRunAutomaton subIncludeAutomaton = includeAutomaton;
137110
int subIncludeState = includeState;
138-
if (includeAutomaton.isAccept(includeState)) {
139-
if (excludeState == -1 || excludeAutomaton.step(excludeState, '.') == -1) {
140-
// the exclude has no chances to match inner properties
141-
filtered.put(key, value);
142-
continue;
143-
} else {
144-
// the object matched, so consider that the include matches every inner property
145-
// we only care about excludes now
146-
subIncludeAutomaton = matchAllAutomaton;
147-
subIncludeState = 0;
148-
}
149-
}
150-
151-
if (value instanceof Map) {
152-
111+
// if (includeAutomaton.isAccept(includeState)) {
112+
// while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
113+
// assert token == XContentParser.Token.FIELD_NAME;
114+
// String currentName = parser.currentName();
115+
// parser.nextToken();
116+
// filtered.put(currentName, parser.objectBytes());
117+
// }
118+
// continue;
119+
// }
120+
121+
if (token == XContentParser.Token.START_OBJECT) {
153122
subIncludeState = subIncludeAutomaton.step(subIncludeState, '.');
154123
if (subIncludeState == -1) {
124+
parser.skipChildren();
155125
continue;
156126
}
157-
if (excludeState != -1) {
158-
excludeState = excludeAutomaton.step(excludeState, '.');
159-
}
160-
161-
@SuppressWarnings("unchecked")
162-
Map<String, Object> valueAsMap = (Map<String, Object>) value;
163-
Map<String, Object> filteredValue = filter(
164-
(XContentParser) null,
165-
// valueAsMap,
166-
subIncludeAutomaton,
167-
subIncludeState,
168-
excludeAutomaton,
169-
excludeState,
170-
matchAllAutomaton
171-
);
127+
Map<String, Object> filteredValue = filter(parser, subIncludeAutomaton, subIncludeState, matchAllAutomaton);
172128
if (includeAutomaton.isAccept(includeState) || filteredValue.isEmpty() == false) {
173129
filtered.put(key, filteredValue);
174130
}
175131

176-
} else if (value instanceof Iterable) {
177-
178-
List<Object> filteredValue = filter(
179-
(Iterable<?>) value,
180-
subIncludeAutomaton,
181-
subIncludeState,
182-
excludeAutomaton,
183-
excludeState,
184-
matchAllAutomaton
185-
);
132+
} else if (token == XContentParser.Token.START_ARRAY) {
133+
List<Object> filteredValue = filterArray(parser, subIncludeAutomaton, subIncludeState, matchAllAutomaton);
186134
if (includeAutomaton.isAccept(includeState) || filteredValue.isEmpty() == false) {
187135
filtered.put(key, filteredValue);
188136
}
189137

190138
} else {
191-
192139
// leaf property
193-
if (includeAutomaton.isAccept(includeState) && (excludeState == -1 || excludeAutomaton.isAccept(excludeState) == false)) {
194-
filtered.put(key, value);
140+
if (includeAutomaton.isAccept(includeState)) {
141+
filtered.put(key, parser.objectText());
195142
}
196-
197143
}
198-
199144
}
200145
return filtered;
201146
}
202147

203-
private static List<Object> filter(
204-
Iterable<?> iterable,
148+
private static List<Object> filterArray(
149+
XContentParser parser,
205150
CharacterRunAutomaton includeAutomaton,
206151
int initialIncludeState,
207-
CharacterRunAutomaton excludeAutomaton,
208-
int initialExcludeState,
209152
CharacterRunAutomaton matchAllAutomaton
210-
) {
153+
) throws IOException {
211154
List<Object> filtered = new ArrayList<>();
212155
boolean isInclude = includeAutomaton.isAccept(initialIncludeState);
213-
for (Object value : iterable) {
214-
if (value instanceof Map) {
156+
XContentParser.Token token;
157+
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
158+
if (token == XContentParser.Token.START_OBJECT) {
215159
int includeState = includeAutomaton.step(initialIncludeState, '.');
216-
int excludeState = initialExcludeState;
217-
if (excludeState != -1) {
218-
excludeState = excludeAutomaton.step(excludeState, '.');
219-
}
220160
@SuppressWarnings("unchecked")
221-
Map<String, Object> filteredValue = filter(
222-
(XContentParser) null,
223-
// (Map<String, ?>) value,
224-
includeAutomaton,
225-
includeState,
226-
excludeAutomaton,
227-
excludeState,
228-
matchAllAutomaton
229-
);
161+
Map<String, Object> filteredValue = filter(parser, includeAutomaton, includeState, matchAllAutomaton);
230162
if (filteredValue.isEmpty() == false) {
231163
filtered.add(filteredValue);
232164
}
233-
} else if (value instanceof Iterable) {
234-
List<Object> filteredValue = filter(
235-
(Iterable<?>) value,
236-
includeAutomaton,
237-
initialIncludeState,
238-
excludeAutomaton,
239-
initialExcludeState,
240-
matchAllAutomaton
241-
);
165+
} else if (token == XContentParser.Token.START_ARRAY) {
166+
List<Object> filteredValue = filterArray(parser, includeAutomaton, initialIncludeState, matchAllAutomaton);
242167
if (filteredValue.isEmpty() == false) {
243168
filtered.add(filteredValue);
244169
}
245170
} else if (isInclude) {
246171
// #22557: only accept this array value if the key we are on is accepted:
247-
filtered.add(value);
172+
filtered.add(parser.objectBytes());
248173
}
249174
}
250175
return filtered;

0 commit comments

Comments
 (0)