/* * SPDX-License-Identifier: Apache-2.0 * * The OpenSearch Contributors require contributions made to * this file be licensed under the Apache-2.0 license or a * compatible open source license. */ /* * Licensed to Elasticsearch under one or more contributor * license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright * ownership. Elasticsearch licenses this file to you under * the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * Modifications Copyright OpenSearch Contributors. See * GitHub history for details. */ package org.opensearch.search.fetch.subphase; import org.apache.lucene.index.LeafReaderContext; import org.opensearch.common.document.DocumentField; import org.opensearch.index.mapper.MappedFieldType; import org.opensearch.index.mapper.ValueFetcher; import org.opensearch.index.query.QueryShardContext; import org.opensearch.search.lookup.SearchLookup; import org.opensearch.search.lookup.SourceLookup; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; /** * A helper class to {@link FetchFieldsPhase} that's initialized with a list of field patterns to fetch. * Then given a specific document, it can retrieve the corresponding fields from the document's source. * * @opensearch.internal */ public class FieldFetcher { public static FieldFetcher create(QueryShardContext context, SearchLookup searchLookup, Collection fieldAndFormats) { List fieldContexts = new ArrayList<>(); for (FieldAndFormat fieldAndFormat : fieldAndFormats) { String fieldPattern = fieldAndFormat.field; String format = fieldAndFormat.format; Collection concreteFields = context.simpleMatchToIndexNames(fieldPattern); for (String field : concreteFields) { MappedFieldType ft = context.getFieldType(field); if (ft == null || context.isMetadataField(field)) { continue; } ValueFetcher valueFetcher = ft.valueFetcher(context, searchLookup, format); fieldContexts.add(new FieldContext(field, valueFetcher)); } } return new FieldFetcher(fieldContexts); } private final List fieldContexts; private FieldFetcher(List fieldContexts) { this.fieldContexts = fieldContexts; } public Map fetch(SourceLookup sourceLookup, Set ignoredFields) throws IOException { Map documentFields = new HashMap<>(); for (FieldContext context : fieldContexts) { String field = context.fieldName; if (ignoredFields.contains(field)) { continue; } ValueFetcher valueFetcher = context.valueFetcher; List parsedValues = valueFetcher.fetchValues(sourceLookup); if (parsedValues.isEmpty() == false) { documentFields.put(field, new DocumentField(field, parsedValues)); } } return documentFields; } public void setNextReader(LeafReaderContext readerContext) { for (FieldContext field : fieldContexts) { field.valueFetcher.setNextReader(readerContext); } } private static class FieldContext { final String fieldName; final ValueFetcher valueFetcher; FieldContext(String fieldName, ValueFetcher valueFetcher) { this.fieldName = fieldName; this.valueFetcher = valueFetcher; } } }