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

org.eclipse.jnosql.databases.elasticsearch.communication.EntityConverter Maven / Gradle / Ivy

/*
 *  Copyright (c) 2022 Contributors to the Eclipse Foundation
 *   All rights reserved. This program and the accompanying materials
 *   are made available under the terms of the Eclipse Public License v1.0
 *   and Apache License v2.0 which accompanies this distribution.
 *   The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
 *   and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php.
 *
 *   You may elect to redistribute this code under either of these licenses.
 *
 *   Contributors:
 *
 *   Otavio Santana
 *   Maximillian Arruda
 */
package org.eclipse.jnosql.databases.elasticsearch.communication;


import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import org.eclipse.jnosql.communication.ValueUtil;
import org.eclipse.jnosql.communication.semistructured.CommunicationEntity;
import org.eclipse.jnosql.communication.semistructured.Element;
import org.eclipse.jnosql.communication.semistructured.SelectQuery;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import static java.util.Collections.singletonMap;
import static java.util.stream.Collectors.toList;

final class EntityConverter {

    static final String ID_FIELD = "_id";

    static final String ENTITY = "@entity";

    private EntityConverter() {
    }

    static Map getMap(CommunicationEntity entity) {
        Map jsonObject = new HashMap<>();

        entity.elements().stream()
                .filter(d -> !d.name().equals(ID_FIELD))
                .forEach(feedJSON(jsonObject));
        jsonObject.put(ENTITY, entity.name());
        return jsonObject;
    }

    static Stream query(SelectQuery query, ElasticsearchClient client, String index) {
        QueryConverterResult select = QueryConverter.select(client, index, query);

        try {
            Stream statementQueryStream = Stream.empty();
            if (select.hasStatement()) {
                statementQueryStream = executeStatement(query, client, index, select);
            }
            return statementQueryStream.distinct();
        } catch (IOException e) {
            throw new ElasticsearchException("An error to execute a query on elasticsearch", e);
        }
    }

    private static Stream executeStatement(SelectQuery query, ElasticsearchClient client, String index,
                                                           QueryConverterResult select) throws IOException {
        SearchRequest.Builder searchRequest = buildSearchRequestBuilder(query, select);
        searchRequest.index(index);

        SearchResponse searchResponse = client.search(searchRequest.build(), Map.class);

        return getDocumentEntityStream(client, searchResponse);
    }


    private static Consumer feedJSON(Map jsonObject) {
        return d -> {
            Object value = ValueUtil.convert(d.value());
            if (value instanceof Element) {
                Element subDocument = Element.class.cast(value);
                jsonObject.put(d.name(), singletonMap(subDocument.name(), subDocument.get()));
            } else if (isSudDocument(value)) {
                Map subDocument = getMap(value);
                jsonObject.put(d.name(), subDocument);
            } else if (isSudDocumentList(value)) {
                jsonObject.put(d.name(), StreamSupport.stream(Iterable.class.cast(value).spliterator(), false)
                        .map(EntityConverter::getMap).collect(toList()));
            } else {
                jsonObject.put(d.name(), value);
            }
        };
    }

    private static Map getMap(Object value) {
        Map subDocument = new HashMap<>();
        StreamSupport.stream(Iterable.class.cast(value).spliterator(),
                false).forEach(feedJSON(subDocument));
        return subDocument;
    }

    private static boolean isSudDocument(Object value) {
        return value instanceof Iterable && StreamSupport.stream(Iterable.class.cast(value).spliterator(), false).
                allMatch(Element.class::isInstance);
    }

    private static boolean isSudDocumentList(Object value) {
        return value instanceof Iterable && StreamSupport.stream(Iterable.class.cast(value).spliterator(), false).
                allMatch(d -> d instanceof Iterable && isSudDocument(d));
    }

    static Stream getDocumentEntityStream(ElasticsearchClient client, SearchResponse responses) {
        return responses.hits().hits().stream()
                .map(hits -> ElasticsearchEntry.of(hits.id(), hits.source()))
                .filter(ElasticsearchEntry::isNotEmpty)
                .map(ElasticsearchEntry::toEntity);
    }

    private static SearchRequest.Builder buildSearchRequestBuilder(SelectQuery query, QueryConverterResult select) {
        SearchRequest.Builder searchBuilder = new SearchRequest.Builder();

        if (select.hasQuery()) {
            searchBuilder.query(select.statement().build());
        }

        feedBuilder(query, searchBuilder);
        return searchBuilder;
    }

    private static void feedBuilder(SelectQuery query, SearchRequest.Builder searchSource) {
        query.sorts().forEach(d -> {
            if (d.isAscending()) {
                searchSource.sort(s -> s.field(f -> f.field(d.property()).order(SortOrder.Asc)));
            } else {
                searchSource.sort(s -> s.field(f -> f.field(d.property()).order(SortOrder.Desc)));
            }
        });

        int from = (int) query.skip();
        int size = (int) query.limit();
        if (from > 0) {
            searchSource.from(from);
        }
        if (size > 0) {
            searchSource.size(size);
        }
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy