Skip to content

Commit 80456f7

Browse files
committed
Allow loading multiple values from _ignored_source
1 parent 16a7723 commit 80456f7

File tree

4 files changed

+150
-12
lines changed

4 files changed

+150
-12
lines changed

server/src/main/java/org/elasticsearch/index/fieldvisitor/CustomFieldsVisitor.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import org.apache.lucene.index.FieldInfo;
1212
import org.elasticsearch.index.mapper.IgnoredFieldMapper;
13+
import org.elasticsearch.index.mapper.IgnoredSourceFieldMapper;
1314

1415
import java.util.HashSet;
1516
import java.util.Set;
@@ -50,6 +51,11 @@ public Status needsField(FieldInfo fieldInfo) {
5051
if (fields.contains(fieldInfo.name)) {
5152
return Status.YES;
5253
}
54+
55+
if (IgnoredSourceFieldMapper.NAME.equals(fieldInfo.name)) {
56+
return Status.YES;
57+
}
58+
5359
return Status.NO;
5460
}
5561
}

server/src/main/java/org/elasticsearch/index/fieldvisitor/IgnoredSourceFieldLoader.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ public List<String> fieldsToLoad() {
8888

8989
static class SFV extends StoredFieldVisitor {
9090

91-
boolean done;
9291
final List<Object> values = new ArrayList<>();
9392
final Set<String> potentialFieldsInIgnoreSource;
9493

@@ -98,9 +97,7 @@ static class SFV extends StoredFieldVisitor {
9897

9998
@Override
10099
public Status needsField(FieldInfo fieldInfo) throws IOException {
101-
if (done) {
102-
return Status.STOP;
103-
} else if (IgnoredSourceFieldMapper.NAME.equals(fieldInfo.name)) {
100+
if (IgnoredSourceFieldMapper.NAME.equals(fieldInfo.name)) {
104101
return Status.YES;
105102
} else {
106103
return Status.NO;
@@ -111,24 +108,27 @@ public Status needsField(FieldInfo fieldInfo) throws IOException {
111108
public void binaryField(FieldInfo fieldInfo, byte[] value) throws IOException {
112109
var result = IgnoredSourceFieldMapper.decodeIfMatch(value, potentialFieldsInIgnoreSource);
113110
if (result != null) {
114-
// TODO: can't do this in case multiple entries for the same field name. (objects, arrays etc.)
115-
// done = true;
116111
values.add(result);
117112
}
118113
}
119114

120115
void reset() {
121116
values.clear();
122-
done = false;
123117
}
124118

125119
}
126120

127121
static boolean supports(StoredFieldsSpec spec) {
128-
return spec.requiresSource() == false
129-
&& spec.requiresMetadata() == false
130-
&& spec.requiredStoredFields().size() == 1
131-
&& spec.requiredStoredFields().iterator().next().startsWith(IgnoredSourceFieldMapper.NAME);
122+
if (spec.requiresSource() || spec.requiresMetadata()) {
123+
return false;
124+
}
125+
126+
for (String fieldName : spec.requiredStoredFields()) {
127+
if (fieldName.startsWith(IgnoredSourceFieldMapper.NAME) == false) {
128+
return false;
129+
}
130+
}
131+
return true;
132132
}
133133

134134
// TODO: use provided one

server/src/main/java/org/elasticsearch/index/mapper/FallbackSyntheticSourceBlockLoader.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,10 @@ public void read(int docId, StoredFields storedFields, Builder builder) throws I
107107

108108
Map<String, List<IgnoredSourceFieldMapper.NameValue>> valuesForFieldAndParents = new HashMap<>();
109109
for (Object value : ignoredSource) {
110-
IgnoredSourceFieldMapper.NameValue nameValue = (IgnoredSourceFieldMapper.NameValue) value;
110+
IgnoredSourceFieldMapper.NameValue nameValue = (value instanceof IgnoredSourceFieldMapper.NameValue nVal)
111+
? nVal
112+
: IgnoredSourceFieldMapper.decode(value);
113+
111114
if (fieldPaths.contains(nameValue.name())) {
112115
valuesForFieldAndParents.computeIfAbsent(nameValue.name(), k -> new ArrayList<>()).add(nameValue);
113116
}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
---
2+
setup:
3+
- requires:
4+
test_runner_features: allowed_warnings_regex
5+
6+
- do:
7+
indices.create:
8+
index: my-index
9+
body:
10+
settings:
11+
index:
12+
mode: logsdb
13+
mappings:
14+
properties:
15+
"@timestamp":
16+
type: date
17+
host.name:
18+
type: keyword
19+
agent_id:
20+
type: keyword
21+
doc_values: false
22+
store: false
23+
process_id:
24+
type: integer
25+
doc_values: false
26+
store: false
27+
http_method:
28+
type: keyword
29+
doc_values: false
30+
store: true
31+
is_https:
32+
type: boolean
33+
doc_values: false
34+
store: false
35+
location:
36+
type: geo_point
37+
doc_values: false
38+
store: false
39+
message:
40+
type: text
41+
store: false
42+
fields:
43+
raw:
44+
type: keyword
45+
46+
- do:
47+
bulk:
48+
index: my-index
49+
refresh: true
50+
body:
51+
- { "index": { } }
52+
- { "@timestamp": "2024-02-12T10:30:00Z", "host.name": "foo", "agent_id": "darth-vader", "process_id": 101, "http_method": "GET", "is_https": false, "location": { "lat": 40.7128, "lon": -74.0060 }, "message": "No, I am your father." }
53+
- { "index": { } }
54+
- { "@timestamp": "2024-02-12T10:31:00Z", "host.name": "bar", "agent_id": "yoda", "process_id": 102, "http_method": "PUT", "is_https": false, "location": { "lat": 40.7128, "lon": -74.0060 }, "message": "Do. Or do not. There is no try." }
55+
- { "index": { } }
56+
- { "@timestamp": "2024-02-12T10:32:00Z", "host.name": "foo", "agent_id": "obi-wan", "process_id": 103, "http_method": "GET", "is_https": false, "location": { "lat": 40.7128, "lon": -74.0060 }, "message": "May the force be with you." }
57+
- { "index": { } }
58+
- { "@timestamp": "2024-02-12T10:33:00Z", "host.name": "baz", "agent_id": "darth-vader", "process_id": 102, "http_method": "POST", "is_https": true, "location": { "lat": 40.7128, "lon": -74.0060 }, "message": "I find your lack of faith disturbing." }
59+
- { "index": { } }
60+
- { "@timestamp": "2024-02-12T10:34:00Z", "host.name": "baz", "agent_id": "yoda", "process_id": 104, "http_method": "POST", "is_https": false, "location": { "lat": 40.7128, "lon": -74.0060 }, "message": "Wars not make one great." }
61+
- { "index": { } }
62+
- { "@timestamp": "2024-02-12T10:35:00Z", "host.name": "foo", "agent_id": "obi-wan", "process_id": 105, "http_method": "GET", "is_https": false, "location": { "lat": 40.7128, "lon": -74.0060 }, "message": "That's no moon. It's a space station." }
63+
64+
---
65+
teardown:
66+
- do:
67+
indices.delete:
68+
index: my-index
69+
70+
---
71+
"Simple from":
72+
- do:
73+
esql.query:
74+
body:
75+
query: 'FROM my-index | SORT host.name, @timestamp | LIMIT 1'
76+
77+
- match: { columns.0.name: "@timestamp" }
78+
- match: { columns.0.type: "date" }
79+
- match: { columns.1.name: "agent_id" }
80+
- match: { columns.1.type: "keyword" }
81+
- match: { columns.2.name: "host.name" }
82+
- match: { columns.2.type: "keyword" }
83+
- match: { columns.3.name: "http_method" }
84+
- match: { columns.3.type: "keyword" }
85+
- match: { columns.4.name: "is_https" }
86+
- match: { columns.4.type: "boolean" }
87+
- match: { columns.5.name: "location" }
88+
- match: { columns.5.type: "geo_point" }
89+
- match: { columns.6.name: "message" }
90+
- match: { columns.6.type: "text" }
91+
- match: { columns.7.name: "message.raw" }
92+
- match: { columns.7.type: "keyword" }
93+
- match: { columns.8.name: "process_id" }
94+
- match: { columns.8.type: "integer" }
95+
96+
- match: { values.0.0: "2024-02-12T10:31:00.000Z" }
97+
- match: { values.0.1: "yoda" }
98+
- match: { values.0.2: "bar" }
99+
- match: { values.0.3: "PUT" }
100+
- match: { values.0.4: false }
101+
- match: { values.0.5: "POINT (-74.006 40.7128)" }
102+
- match: { values.0.6: "Do. Or do not. There is no try." }
103+
- match: { values.0.7: "Do. Or do not. There is no try." }
104+
- match: { values.0.8: 102 }
105+
106+
---
107+
"Simple from keyword fields":
108+
- do:
109+
esql.query:
110+
body:
111+
query: 'FROM my-index | SORT host.name, @timestamp | KEEP agent_id, http_method | LIMIT 10'
112+
113+
- match: { columns.0.name: "agent_id" }
114+
- match: { columns.0.type: "keyword" }
115+
- match: { columns.1.name: "http_method" }
116+
- match: { columns.1.type: "keyword" }
117+
118+
- match: { values.0.0: "yoda" }
119+
- match: { values.0.1: "PUT" }
120+
- match: { values.1.0: "darth-vader" }
121+
- match: { values.1.1: "POST" }
122+
- match: { values.2.0: "yoda" }
123+
- match: { values.2.1: "POST" }
124+
- match: { values.3.0: "darth-vader" }
125+
- match: { values.3.1: "GET" }
126+
- match: { values.4.0: "obi-wan" }
127+
- match: { values.4.1: "GET" }
128+
- match: { values.5.0: "obi-wan" }
129+
- match: { values.5.1: "GET" }

0 commit comments

Comments
 (0)