All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.elasticsearch.action.fieldcaps.ResponseRewriter Maven / Gradle / Ivy

/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0 and the Server Side Public License, v 1; you may not use this file except
 * in compliance with, at your election, the Elastic License 2.0 or the Server
 * Side Public License, v 1.
 */

package org.elasticsearch.action.fieldcaps;

import org.elasticsearch.Version;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * Applies field type filters to field caps responses that come from earlier versions of ES
 * that do not support filtering directly.
 */
final class ResponseRewriter {

    public static Map rewriteOldResponses(
        Version version,
        Map input,
        String[] filters,
        String[] allowedTypes
    ) {
        if (version.onOrAfter(Version.V_8_2_0)) {
            return input;   // nothing needs to be done
        }
        Function transformer = buildTransformer(input, filters, allowedTypes);
        Map rewritten = new HashMap<>();
        for (var entry : input.entrySet()) {
            IndexFieldCapabilities fc = transformer.apply(entry.getValue());
            if (fc != null) {
                rewritten.put(entry.getKey(), fc);
            }
        }
        return rewritten;
    }

    private static Function buildTransformer(
        Map input,
        String[] filters,
        String[] allowedTypes
    ) {
        Predicate test = ifc -> true;
        Set objects = null;
        Set nestedObjects = null;
        if (allowedTypes.length > 0) {
            Set at = Set.of(allowedTypes);
            test = test.and(ifc -> at.contains(ifc.getType()));
        }
        for (String filter : filters) {
            if ("-parent".equals(filter)) {
                test = test.and(fc -> fc.getType().equals("nested") == false && fc.getType().equals("object") == false);
            }
            if ("-metadata".equals(filter)) {
                test = test.and(fc -> fc.isMetadatafield() == false);
            }
            if ("+metadata".equals(filter)) {
                test = test.and(IndexFieldCapabilities::isMetadatafield);
            }
            if ("-nested".equals(filter)) {
                if (nestedObjects == null) {
                    nestedObjects = findTypes("nested", input);
                }
                Set no = nestedObjects;
                test = test.and(fc -> isNestedField(fc.getName(), no) == false);
            }
            if ("-multifield".equals(filter)) {
                // immediate parent is not an object field
                if (objects == null) {
                    objects = findTypes("object", input);
                }
                Set o = objects;
                test = test.and(fc -> isNotMultifield(fc.getName(), o));
            }
        }
        Predicate finalTest = test;
        return fc -> {
            if (finalTest.test(fc) == false) {
                return null;
            }
            return fc;
        };
    }

    private static Set findTypes(String type, Map fieldCaps) {
        return fieldCaps.entrySet()
            .stream()
            .filter(entry -> type.equals(entry.getValue().getType()))
            .map(Map.Entry::getKey)
            .collect(Collectors.toSet());
    }

    private static boolean isNestedField(String field, Set nestedParents) {
        for (String parent : nestedParents) {
            if (field.startsWith(parent + ".") || field.equals(parent)) {
                return true;
            }
        }
        return false;
    }

    private static boolean isNotMultifield(String field, Set objectFields) {
        int lastDotPos = field.lastIndexOf(".");
        if (lastDotPos == -1) {
            return true;
        }
        String parent = field.substring(0, lastDotPos);
        return objectFields.contains(parent);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy