Search in sources :

Example 1 with SourceLookup

use of org.elasticsearch.search.lookup.SourceLookup in project elasticsearch by elastic.

the class FetchPhase method createSearchHit.

private SearchHit createSearchHit(SearchContext context, FieldsVisitor fieldsVisitor, int docId, int subDocId, LeafReaderContext subReaderContext) {
    if (fieldsVisitor == null) {
        return new SearchHit(docId);
    }
    loadStoredFields(context, subReaderContext, fieldsVisitor, subDocId);
    fieldsVisitor.postProcess(context.mapperService());
    Map<String, SearchHitField> searchFields = null;
    if (!fieldsVisitor.fields().isEmpty()) {
        searchFields = new HashMap<>(fieldsVisitor.fields().size());
        for (Map.Entry<String, List<Object>> entry : fieldsVisitor.fields().entrySet()) {
            searchFields.put(entry.getKey(), new SearchHitField(entry.getKey(), entry.getValue()));
        }
    }
    DocumentMapper documentMapper = context.mapperService().documentMapper(fieldsVisitor.uid().type());
    Text typeText;
    if (documentMapper == null) {
        typeText = new Text(fieldsVisitor.uid().type());
    } else {
        typeText = documentMapper.typeText();
    }
    SearchHit searchHit = new SearchHit(docId, fieldsVisitor.uid().id(), typeText, searchFields);
    // Set _source if requested.
    SourceLookup sourceLookup = context.lookup().source();
    sourceLookup.setSegmentAndDocument(subReaderContext, subDocId);
    if (fieldsVisitor.source() != null) {
        sourceLookup.setSource(fieldsVisitor.source());
    }
    return searchHit;
}
Also used : SourceLookup(org.elasticsearch.search.lookup.SourceLookup) SearchHit(org.elasticsearch.search.SearchHit) DocumentMapper(org.elasticsearch.index.mapper.DocumentMapper) SearchHitField(org.elasticsearch.search.SearchHitField) ArrayList(java.util.ArrayList) List(java.util.List) Text(org.elasticsearch.common.text.Text) HashMap(java.util.HashMap) Map(java.util.Map)

Example 2 with SourceLookup

use of org.elasticsearch.search.lookup.SourceLookup in project elasticsearch by elastic.

the class FetchPhase method createNestedSearchHit.

private SearchHit createNestedSearchHit(SearchContext context, int nestedTopDocId, int nestedSubDocId, int rootSubDocId, Set<String> fieldNames, List<String> fieldNamePatterns, LeafReaderContext subReaderContext) throws IOException {
    // Also if highlighting is requested on nested documents we need to fetch the _source from the root document,
    // otherwise highlighting will attempt to fetch the _source from the nested doc, which will fail,
    // because the entire _source is only stored with the root document.
    final FieldsVisitor rootFieldsVisitor = new FieldsVisitor(context.sourceRequested() || context.highlight() != null);
    loadStoredFields(context, subReaderContext, rootFieldsVisitor, rootSubDocId);
    rootFieldsVisitor.postProcess(context.mapperService());
    Map<String, SearchHitField> searchFields = getSearchFields(context, nestedSubDocId, fieldNames, fieldNamePatterns, subReaderContext);
    DocumentMapper documentMapper = context.mapperService().documentMapper(rootFieldsVisitor.uid().type());
    SourceLookup sourceLookup = context.lookup().source();
    sourceLookup.setSegmentAndDocument(subReaderContext, nestedSubDocId);
    ObjectMapper nestedObjectMapper = documentMapper.findNestedObjectMapper(nestedSubDocId, context, subReaderContext);
    assert nestedObjectMapper != null;
    SearchHit.NestedIdentity nestedIdentity = getInternalNestedIdentity(context, nestedSubDocId, subReaderContext, documentMapper, nestedObjectMapper);
    BytesReference source = rootFieldsVisitor.source();
    if (source != null) {
        Tuple<XContentType, Map<String, Object>> tuple = XContentHelper.convertToMap(source, true);
        Map<String, Object> sourceAsMap = tuple.v2();
        // Isolate the nested json array object that matches with nested hit and wrap it back into the same json
        // structure with the nested json array object being the actual content. The latter is important, so that
        // features like source filtering and highlighting work consistent regardless of whether the field points
        // to a json object array for consistency reasons on how we refer to fields
        Map<String, Object> nestedSourceAsMap = new HashMap<>();
        Map<String, Object> current = nestedSourceAsMap;
        for (SearchHit.NestedIdentity nested = nestedIdentity; nested != null; nested = nested.getChild()) {
            String nestedPath = nested.getField().string();
            current.put(nestedPath, new HashMap<>());
            Object extractedValue = XContentMapValues.extractValue(nestedPath, sourceAsMap);
            List<Map<String, Object>> nestedParsedSource;
            if (extractedValue instanceof List) {
                // nested field has an array value in the _source
                nestedParsedSource = (List<Map<String, Object>>) extractedValue;
            } else if (extractedValue instanceof Map) {
                // nested field has an object value in the _source. This just means the nested field has just one inner object, which is valid, but uncommon.
                nestedParsedSource = Collections.singletonList((Map<String, Object>) extractedValue);
            } else {
                throw new IllegalStateException("extracted source isn't an object or an array");
            }
            sourceAsMap = nestedParsedSource.get(nested.getOffset());
            if (nested.getChild() == null) {
                current.put(nestedPath, sourceAsMap);
            } else {
                Map<String, Object> next = new HashMap<>();
                current.put(nestedPath, next);
                current = next;
            }
        }
        context.lookup().source().setSource(nestedSourceAsMap);
        XContentType contentType = tuple.v1();
        BytesReference nestedSource = contentBuilder(contentType).map(sourceAsMap).bytes();
        context.lookup().source().setSource(nestedSource);
        context.lookup().source().setSourceContentType(contentType);
    }
    return new SearchHit(nestedTopDocId, rootFieldsVisitor.uid().id(), documentMapper.typeText(), nestedIdentity, searchFields);
}
Also used : BytesReference(org.elasticsearch.common.bytes.BytesReference) FieldsVisitor(org.elasticsearch.index.fieldvisitor.FieldsVisitor) CustomFieldsVisitor(org.elasticsearch.index.fieldvisitor.CustomFieldsVisitor) SourceLookup(org.elasticsearch.search.lookup.SourceLookup) SearchHit(org.elasticsearch.search.SearchHit) HashMap(java.util.HashMap) DocumentMapper(org.elasticsearch.index.mapper.DocumentMapper) XContentType(org.elasticsearch.common.xcontent.XContentType) SearchHitField(org.elasticsearch.search.SearchHitField) ArrayList(java.util.ArrayList) List(java.util.List) HashMap(java.util.HashMap) Map(java.util.Map) ObjectMapper(org.elasticsearch.index.mapper.ObjectMapper)

Example 3 with SourceLookup

use of org.elasticsearch.search.lookup.SourceLookup in project elasticsearch by elastic.

the class SourceScoreOrderFragmentsBuilder method getFields.

@Override
protected Field[] getFields(IndexReader reader, int docId, String fieldName) throws IOException {
    // we know its low level reader, and matching docId, since that's how we call the highlighter with
    SourceLookup sourceLookup = searchContext.lookup().source();
    sourceLookup.setSegmentAndDocument((LeafReaderContext) reader.getContext(), docId);
    List<Object> values = sourceLookup.extractRawValues(mapper.fieldType().name());
    Field[] fields = new Field[values.size()];
    for (int i = 0; i < values.size(); i++) {
        fields[i] = new Field(mapper.fieldType().name(), values.get(i).toString(), TextField.TYPE_NOT_STORED);
    }
    return fields;
}
Also used : Field(org.apache.lucene.document.Field) TextField(org.apache.lucene.document.TextField) SourceLookup(org.elasticsearch.search.lookup.SourceLookup)

Example 4 with SourceLookup

use of org.elasticsearch.search.lookup.SourceLookup in project elasticsearch by elastic.

the class SourceSimpleFragmentsBuilder method getFields.

@Override
protected Field[] getFields(IndexReader reader, int docId, String fieldName) throws IOException {
    // we know its low level reader, and matching docId, since that's how we call the highlighter with
    SourceLookup sourceLookup = searchContext.lookup().source();
    sourceLookup.setSegmentAndDocument((LeafReaderContext) reader.getContext(), docId);
    List<Object> values = sourceLookup.extractRawValues(mapper.fieldType().name());
    if (values.isEmpty()) {
        return EMPTY_FIELDS;
    }
    Field[] fields = new Field[values.size()];
    for (int i = 0; i < values.size(); i++) {
        fields[i] = new Field(mapper.fieldType().name(), values.get(i).toString(), TextField.TYPE_NOT_STORED);
    }
    return fields;
}
Also used : Field(org.apache.lucene.document.Field) TextField(org.apache.lucene.document.TextField) SourceLookup(org.elasticsearch.search.lookup.SourceLookup)

Example 5 with SourceLookup

use of org.elasticsearch.search.lookup.SourceLookup in project elasticsearch by elastic.

the class UpdateHelper method extractGetResult.

/**
     * Applies {@link UpdateRequest#fetchSource()} to the _source of the updated document to be returned in a update response.
     * For BWC this function also extracts the {@link UpdateRequest#fields()} from the updated document to be returned in a update response
     */
public GetResult extractGetResult(final UpdateRequest request, String concreteIndex, long version, final Map<String, Object> source, XContentType sourceContentType, @Nullable final BytesReference sourceAsBytes) {
    if ((request.fields() == null || request.fields().length == 0) && (request.fetchSource() == null || request.fetchSource().fetchSource() == false)) {
        return null;
    }
    SourceLookup sourceLookup = new SourceLookup();
    sourceLookup.setSource(source);
    boolean sourceRequested = false;
    Map<String, GetField> fields = null;
    if (request.fields() != null && request.fields().length > 0) {
        for (String field : request.fields()) {
            if (field.equals("_source")) {
                sourceRequested = true;
                continue;
            }
            Object value = sourceLookup.extractValue(field);
            if (value != null) {
                if (fields == null) {
                    fields = new HashMap<>(2);
                }
                GetField getField = fields.get(field);
                if (getField == null) {
                    getField = new GetField(field, new ArrayList<>(2));
                    fields.put(field, getField);
                }
                getField.getValues().add(value);
            }
        }
    }
    BytesReference sourceFilteredAsBytes = sourceAsBytes;
    if (request.fetchSource() != null && request.fetchSource().fetchSource()) {
        sourceRequested = true;
        if (request.fetchSource().includes().length > 0 || request.fetchSource().excludes().length > 0) {
            Object value = sourceLookup.filter(request.fetchSource());
            try {
                final int initialCapacity = Math.min(1024, sourceAsBytes.length());
                BytesStreamOutput streamOutput = new BytesStreamOutput(initialCapacity);
                try (XContentBuilder builder = new XContentBuilder(sourceContentType.xContent(), streamOutput)) {
                    builder.value(value);
                    sourceFilteredAsBytes = builder.bytes();
                }
            } catch (IOException e) {
                throw new ElasticsearchException("Error filtering source", e);
            }
        }
    }
    // TODO when using delete/none, we can still return the source as bytes by generating it (using the sourceContentType)
    return new GetResult(concreteIndex, request.type(), request.id(), version, true, sourceRequested ? sourceFilteredAsBytes : null, fields);
}
Also used : BytesReference(org.elasticsearch.common.bytes.BytesReference) GetField(org.elasticsearch.index.get.GetField) SourceLookup(org.elasticsearch.search.lookup.SourceLookup) GetResult(org.elasticsearch.index.get.GetResult) ArrayList(java.util.ArrayList) IOException(java.io.IOException) ElasticsearchException(org.elasticsearch.ElasticsearchException) BytesStreamOutput(org.elasticsearch.common.io.stream.BytesStreamOutput) XContentBuilder(org.elasticsearch.common.xcontent.XContentBuilder)

Aggregations

SourceLookup (org.elasticsearch.search.lookup.SourceLookup)7 ArrayList (java.util.ArrayList)3 IOException (java.io.IOException)2 HashMap (java.util.HashMap)2 List (java.util.List)2 Map (java.util.Map)2 Field (org.apache.lucene.document.Field)2 TextField (org.apache.lucene.document.TextField)2 ElasticsearchException (org.elasticsearch.ElasticsearchException)2 BytesReference (org.elasticsearch.common.bytes.BytesReference)2 BytesStreamOutput (org.elasticsearch.common.io.stream.BytesStreamOutput)2 XContentBuilder (org.elasticsearch.common.xcontent.XContentBuilder)2 CustomFieldsVisitor (org.elasticsearch.index.fieldvisitor.CustomFieldsVisitor)2 DocumentMapper (org.elasticsearch.index.mapper.DocumentMapper)2 SearchHit (org.elasticsearch.search.SearchHit)2 SearchHitField (org.elasticsearch.search.SearchHitField)2 Text (org.elasticsearch.common.text.Text)1 XContentType (org.elasticsearch.common.xcontent.XContentType)1 FieldsVisitor (org.elasticsearch.index.fieldvisitor.FieldsVisitor)1 GetField (org.elasticsearch.index.get.GetField)1