Skip to content

Commit 2bbef1d

Browse files
committed
Let IgnoredSourceFieldLoader.SFV decode NameValue
1 parent 4f6bacf commit 2bbef1d

File tree

4 files changed

+54
-17
lines changed

4 files changed

+54
-17
lines changed

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

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,39 @@
1313
import org.apache.lucene.index.LeafReader;
1414
import org.apache.lucene.index.LeafReaderContext;
1515
import org.apache.lucene.index.StoredFieldVisitor;
16-
import org.apache.lucene.util.BytesRef;
1716
import org.elasticsearch.common.CheckedBiConsumer;
1817
import org.elasticsearch.common.bytes.BytesReference;
1918
import org.elasticsearch.common.lucene.index.SequentialStoredFieldsLeafReader;
19+
import org.elasticsearch.index.mapper.FallbackSyntheticSourceBlockLoader;
2020
import org.elasticsearch.index.mapper.IgnoredSourceFieldMapper;
2121
import org.elasticsearch.search.fetch.StoredFieldsSpec;
2222

2323
import java.io.IOException;
2424
import java.util.ArrayList;
25+
import java.util.HashSet;
2526
import java.util.List;
2627
import java.util.Map;
28+
import java.util.Set;
2729

2830
class IgnoredSourceFieldLoader extends StoredFieldLoader {
2931

32+
final Set<String> potentialFieldsInIgnoreSource;
33+
34+
IgnoredSourceFieldLoader(StoredFieldsSpec spec) {
35+
Set<String> potentialFieldsInIgnoreSource = new HashSet<>();
36+
for (String requiredStoredField : spec.requiredStoredFields()) {
37+
if (requiredStoredField.startsWith(IgnoredSourceFieldMapper.NAME)) {
38+
String fieldName = requiredStoredField.substring(IgnoredSourceFieldMapper.NAME.length());
39+
potentialFieldsInIgnoreSource.addAll(FallbackSyntheticSourceBlockLoader.splitIntoFieldPaths(fieldName));
40+
}
41+
}
42+
this.potentialFieldsInIgnoreSource = potentialFieldsInIgnoreSource;
43+
}
44+
3045
@Override
3146
public LeafStoredFieldLoader getLoader(LeafReaderContext ctx, int[] docs) throws IOException {
3247
var reader = sequentialReader(ctx);
33-
var visitor = new SFV();
48+
var visitor = new SFV(potentialFieldsInIgnoreSource);
3449
return new LeafStoredFieldLoader() {
3550

3651
private int doc = -1;
@@ -73,29 +88,37 @@ public List<String> fieldsToLoad() {
7388

7489
static class SFV extends StoredFieldVisitor {
7590

76-
boolean processing;
91+
boolean done;
7792
final List<Object> values = new ArrayList<>();
93+
final Set<String> potentialFieldsInIgnoreSource;
94+
95+
SFV(Set<String> potentialFieldsInIgnoreSource) {
96+
this.potentialFieldsInIgnoreSource = potentialFieldsInIgnoreSource;
97+
}
7898

7999
@Override
80100
public Status needsField(FieldInfo fieldInfo) throws IOException {
81-
if (IgnoredSourceFieldMapper.NAME.equals(fieldInfo.name)) {
82-
processing = true;
83-
return Status.YES;
84-
} else if (processing) {
101+
if (done) {
85102
return Status.STOP;
103+
} else if (IgnoredSourceFieldMapper.NAME.equals(fieldInfo.name)) {
104+
return Status.YES;
105+
} else {
106+
return Status.NO;
86107
}
87-
88-
return Status.NO;
89108
}
90109

91110
@Override
92111
public void binaryField(FieldInfo fieldInfo, byte[] value) throws IOException {
93-
values.add(new BytesRef(value));
112+
var result = IgnoredSourceFieldMapper.decodeIfMatch(value, potentialFieldsInIgnoreSource);
113+
if (result != null) {
114+
done = true;
115+
values.add(result);
116+
}
94117
}
95118

96119
void reset() {
97120
values.clear();
98-
processing = false;
121+
done = false;
99122
}
100123

101124
}
@@ -104,7 +127,7 @@ static boolean supports(StoredFieldsSpec spec) {
104127
return spec.requiresSource() == false
105128
&& spec.requiresMetadata() == false
106129
&& spec.requiredStoredFields().size() == 1
107-
&& spec.requiredStoredFields().contains(IgnoredSourceFieldMapper.NAME);
130+
&& spec.requiredStoredFields().iterator().next().startsWith(IgnoredSourceFieldMapper.NAME);
108131
}
109132

110133
// TODO: use provided one

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public static StoredFieldLoader fromSpec(StoredFieldsSpec spec) {
5151
return StoredFieldLoader.empty();
5252
}
5353
if (IgnoredSourceFieldLoader.supports(spec)) {
54-
return new IgnoredSourceFieldLoader();
54+
return new IgnoredSourceFieldLoader(spec);
5555
}
5656
return create(spec.requiresSource(), spec.requiredStoredFields());
5757
}
@@ -95,7 +95,7 @@ public static StoredFieldLoader fromSpecSequential(StoredFieldsSpec spec) {
9595
return StoredFieldLoader.empty();
9696
}
9797
if (IgnoredSourceFieldLoader.supports(spec)) {
98-
return new IgnoredSourceFieldLoader();
98+
return new IgnoredSourceFieldLoader(spec);
9999
}
100100

101101
List<String> fieldsToLoad = fieldsToLoad(spec.requiresSource(), spec.requiredStoredFields());

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public RowStrideReader rowStrideReader(LeafReaderContext context) throws IOExcep
5959

6060
@Override
6161
public StoredFieldsSpec rowStrideStoredFieldSpec() {
62-
return new StoredFieldsSpec(false, false, Set.of(IgnoredSourceFieldMapper.NAME));
62+
return new StoredFieldsSpec(false, false, Set.of(IgnoredSourceFieldMapper.NAME + "." + fieldName));
6363
}
6464

6565
@Override
@@ -72,7 +72,7 @@ public SortedSetDocValues ordinals(LeafReaderContext context) throws IOException
7272
throw new UnsupportedOperationException();
7373
}
7474

75-
static Set<String> splitIntoFieldPaths(String fieldName) {
75+
public static Set<String> splitIntoFieldPaths(String fieldName) {
7676
var paths = new HashSet<String>();
7777
paths.add("_doc");
7878
var current = new StringBuilder();
@@ -107,7 +107,7 @@ 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.decode(value);
110+
IgnoredSourceFieldMapper.NameValue nameValue = (IgnoredSourceFieldMapper.NameValue) value;
111111
if (fieldPaths.contains(nameValue.name())) {
112112
valuesForFieldAndParents.computeIfAbsent(nameValue.name(), k -> new ArrayList<>()).add(nameValue);
113113
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,20 @@ static NameValue decode(Object field) {
186186
return new NameValue(name, parentOffset, value, null);
187187
}
188188

189+
public static NameValue decodeIfMatch(byte[] bytes, Set<String> potentialFieldsInIgnoreSource) {
190+
int encodedSize = ByteUtils.readIntLE(bytes, 0);
191+
int nameSize = encodedSize % PARENT_OFFSET_IN_NAME_OFFSET;
192+
int parentOffset = encodedSize / PARENT_OFFSET_IN_NAME_OFFSET;
193+
194+
String name = new String(bytes, 4, nameSize, StandardCharsets.UTF_8);
195+
if (potentialFieldsInIgnoreSource.contains(name)) {
196+
BytesRef value = new BytesRef(bytes, 4 + nameSize, bytes.length - nameSize - 4);
197+
return new NameValue(name, parentOffset, value, null);
198+
} else {
199+
return null;
200+
}
201+
}
202+
189203
// In rare cases decoding values stored in this field can fail leading to entire source
190204
// not being available.
191205
// We would like to have an option to lose some values in synthetic source

0 commit comments

Comments
 (0)