Change ParentFieldSubFetchPhase to create doc values iterator once per segment (#26815)
This commit is contained in:
parent
0358bb5f34
commit
aade2f6d63
|
@ -20,43 +20,79 @@
|
|||
package org.elasticsearch.search.fetch.subphase;
|
||||
|
||||
import org.apache.lucene.index.LeafReader;
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.index.ReaderUtil;
|
||||
import org.apache.lucene.index.SortedDocValues;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.ExceptionsHelper;
|
||||
import org.elasticsearch.common.document.DocumentField;
|
||||
import org.elasticsearch.index.mapper.MapperService;
|
||||
import org.elasticsearch.index.mapper.ParentFieldMapper;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.fetch.FetchSubPhase;
|
||||
import org.elasticsearch.search.internal.SearchContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public final class ParentFieldSubFetchPhase implements FetchSubPhase {
|
||||
|
||||
@Override
|
||||
public void hitExecute(SearchContext context, HitContext hitContext) {
|
||||
public void hitsExecute(SearchContext context, SearchHit[] hits) throws IOException {
|
||||
if (context.storedFieldsContext() != null && context.storedFieldsContext().fetchFields() == false) {
|
||||
return ;
|
||||
}
|
||||
ParentFieldMapper parentFieldMapper = context.mapperService().documentMapper(hitContext.hit().getType()).parentFieldMapper();
|
||||
|
||||
hits = hits.clone(); // don't modify the incoming hits
|
||||
Arrays.sort(hits, Comparator.comparingInt(SearchHit::docId));
|
||||
|
||||
MapperService mapperService = context.mapperService();
|
||||
Set<String> parentFields = new HashSet<>();
|
||||
for (SearchHit hit : hits) {
|
||||
ParentFieldMapper parentFieldMapper = mapperService.documentMapper(hit.getType()).parentFieldMapper();
|
||||
if (parentFieldMapper.active()) {
|
||||
parentFields.add(parentFieldMapper.name());
|
||||
}
|
||||
}
|
||||
|
||||
int lastReaderId = -1;
|
||||
Map<String, SortedDocValues> docValuesMap = new HashMap<>();
|
||||
for (SearchHit hit : hits) {
|
||||
ParentFieldMapper parentFieldMapper = mapperService.documentMapper(hit.getType()).parentFieldMapper();
|
||||
if (parentFieldMapper.active() == false) {
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
String parentId = getParentId(parentFieldMapper, hitContext.reader(), hitContext.docId());
|
||||
if (parentId == null) {
|
||||
int readerId = ReaderUtil.subIndex(hit.docId(), context.searcher().getIndexReader().leaves());
|
||||
LeafReaderContext subReaderContext = context.searcher().getIndexReader().leaves().get(readerId);
|
||||
if (lastReaderId != readerId) {
|
||||
docValuesMap.clear();
|
||||
for (String field : parentFields) {
|
||||
docValuesMap.put(field, subReaderContext.reader().getSortedDocValues(field));
|
||||
}
|
||||
lastReaderId = readerId;
|
||||
}
|
||||
int docId = hit.docId() - subReaderContext.docBase;
|
||||
SortedDocValues values = docValuesMap.get(parentFieldMapper.name());
|
||||
if (values != null && values.advanceExact(docId)) {
|
||||
BytesRef binaryValue = values.binaryValue();
|
||||
String value = binaryValue.length > 0 ? binaryValue.utf8ToString() : null;
|
||||
if (value == null) {
|
||||
// hit has no _parent field. Can happen for nested inner hits if parent hit is a p/c document.
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
Map<String, DocumentField> fields = hitContext.hit().fieldsOrNull();
|
||||
Map<String, DocumentField> fields = hit.fieldsOrNull();
|
||||
if (fields == null) {
|
||||
fields = new HashMap<>();
|
||||
hitContext.hit().fields(fields);
|
||||
hit.fields(fields);
|
||||
}
|
||||
fields.put(ParentFieldMapper.NAME, new DocumentField(ParentFieldMapper.NAME, Collections.singletonList(value)));
|
||||
}
|
||||
}
|
||||
fields.put(ParentFieldMapper.NAME, new DocumentField(ParentFieldMapper.NAME, Collections.singletonList(parentId)));
|
||||
}
|
||||
|
||||
public static String getParentId(ParentFieldMapper fieldMapper, LeafReader reader, int docId) {
|
||||
|
@ -72,5 +108,4 @@ public final class ParentFieldSubFetchPhase implements FetchSubPhase {
|
|||
throw ExceptionsHelper.convertToElastic(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue