Package com.codetroopers.play.elasticsearch

Source Code of com.codetroopers.play.elasticsearch.IndexQuery

package com.codetroopers.play.elasticsearch;

import com.codetroopers.play.elasticsearch.jest.JestRichResult;
import com.codetroopers.play.elasticsearch.jest.JestSearchRequestBuilder;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import io.searchbox.core.search.facet.Facet;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.elasticsearch.index.query.FilterBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.facet.FacetBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import play.Logger;
import play.libs.F;

import javax.annotation.Nullable;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

/**
* An ElasticSearch query
*
* @param <T> extends Index
*/
public class IndexQuery<T extends Index> {

    /**
     * Objet retourné dans les résultats
     */
    private final Class<T> clazz;

    /**
     * Query searchRequestBuilder
     */
    private QueryBuilder builder = QueryBuilders.matchAllQuery();
    private String query = null;
    private List<FacetBuilder> facets = new ArrayList<>();
    private List<SortBuilder> sorts = new ArrayList<>();

    private int from = -1;
    private int size = -1;
    private boolean explain = false;
    private boolean noField = false;

    public IndexQuery(Class<T> clazz) {
        Validate.notNull(clazz, "clazz cannot be null");
        this.clazz = clazz;
    }

    public IndexQuery<T> setBuilder(QueryBuilder builder) {
        this.builder = builder;

        return this;
    }

    public void setQuery(String query) {
        this.query = query;
    }

    public void setNoField(boolean noField) {
        this.noField = noField;
    }

    /**
     * Sets from
     *
     * @param from record index to start from
     * @return self
     */
    public IndexQuery<T> from(int from) {
        this.from = from;

        return this;
    }

    /**
     * Sets fetch size
     *
     * @param size the fetch size
     * @return self
     */
    public IndexQuery<T> size(int size) {
        this.size = size;

        return this;
    }

    public IndexQuery<T> setExplain(boolean explain) {
        this.explain = explain;

        return this;
    }

    /**
     * Adds a facet
     *
     * @param facet the facet
     * @return self
     */
    public IndexQuery<T> addFacet(FacetBuilder facet) {
        Validate.notNull(facet, "facet cannot be null");
        facets.add(facet);

        return this;
    }

    /**
     * Sorts the result by a specific field
     *
     * @param field the sort field
     * @param order the sort order
     * @return self
     */
    public IndexQuery<T> addSort(String field, SortOrder order) {
        Validate.notEmpty(field, "field cannot be null");
        Validate.notNull(order, "order cannot be null");
        sorts.add(SortBuilders.fieldSort(field).order(order));

        return this;
    }

    /**
     * Adds a generic {@link SortBuilder}
     *
     * @param sort the sort searchRequestBuilder
     * @return self
     */
    public IndexQuery<T> addSort(SortBuilder sort) {
        Validate.notNull(sort, "sort cannot be null");
        sorts.add(sort);

        return this;
    }

    /**
     * Runs the query
     *
     * @param indexQueryPath
     * @return
     */
    public IndexResults<T> fetch(IndexQueryPath indexQueryPath) {
        return fetch(indexQueryPath, null);
    }

    /**
     * Runs the query with a filter
     *
     * @param indexQueryPath
     * @param filter
     * @return
     */
    public IndexResults<T> fetch(IndexQueryPath indexQueryPath, FilterBuilder filter) {

        JestSearchRequestBuilder request = getSearchRequestBuilder(indexQueryPath, filter);

        return executeSearchRequest(request);
    }

    /**
     * Runs the query asynchronously
     *
     * @param indexQueryPath
     * @return
     */
    public F.Promise<IndexResults<T>> fetchAsync(IndexQueryPath indexQueryPath) {
        return fetchAsync(indexQueryPath, null);
    }

    /**
     * Runs the query asynchronously with a filter
     *
     * @param indexQueryPath
     * @param filter
     * @return
     */
    public F.Promise<IndexResults<T>> fetchAsync(final IndexQueryPath indexQueryPath, final FilterBuilder filter) {
        final F.Promise<JestRichResult> jestResultPromise = getSearchRequestBuilder(indexQueryPath, filter).executeAsync();
        return jestResultPromise.map(new F.Function<JestRichResult, IndexResults<T>>() {
            @Override
            public IndexResults<T> apply(JestRichResult jestResult) throws Throwable {
                return toSearchResults(jestResult);
            }
        });
    }

    public IndexResults<T> executeSearchRequest(JestSearchRequestBuilder request) {

        JestRichResult searchResponse = request.execute();

        if (IndexClient.config.showRequest && searchResponse != null) {
            Logger.debug("ElasticSearch : Response -> " + searchResponse.getJsonString());
        }

        return toSearchResults(searchResponse);
    }

    public JestSearchRequestBuilder getSearchRequestBuilder(IndexQueryPath indexQueryPath) {
        return getSearchRequestBuilder(indexQueryPath, null);
    }

    public JestSearchRequestBuilder getSearchRequestBuilder(FilterBuilder filter) {
        return getSearchRequestBuilder(null, filter);
    }

    public JestSearchRequestBuilder getSearchRequestBuilder(@Nullable IndexQueryPath indexQueryPath, FilterBuilder filter) {

        // Build request
        JestSearchRequestBuilder request = new JestSearchRequestBuilder();
        if (indexQueryPath != null) {
            request.setIndices(indexQueryPath.index)
                    .setTypes(indexQueryPath.type);
        }
        request.setSearchType(io.searchbox.params.SearchType.QUERY_THEN_FETCH)
                .setFilter(filter);

        // set Query
        if (StringUtils.isNotBlank(query)) {
            request.setQuery(query);
        } else {
            request.setQuery(builder);
        }

        // set no Fields -> only return id and type
        if (noField) {
            request.setNoFields();
        }

        // Facets
        for (FacetBuilder facet : facets) {
            request.addFacet(facet);
        }

        // Sorting
        for (SortBuilder sort : sorts) {
            request.addSort(sort);
        }

        // Paging
        if (from > -1) {
            request.setFrom(from);
        }
        if (size > -1) {
            request.setSize(size);
        }

        // Explain
        if (explain) {
            request.setExplain(true);
        }

        if (IndexClient.config.showRequest) {
            if (StringUtils.isNotBlank(query)) {
                Logger.debug("ElasticSearch : Query -> " + query);
            } else {
                Logger.debug("ElasticSearch : Query -> " + builder.toString());
            }
        }
        return request;
    }

    private IndexResults<T> toSearchResults(@NotNull JestRichResult jestRichResult) {
        List<T> results = Lists.newArrayList();
        long count = jestRichResult.getTotalHits();
        List<Facet> facetsResponse = jestRichResult.getFacets();
        for (JestRichResult.Result h : jestRichResult.getHits()) {
            results.add(h.getObject(clazz));
        }
        if (Logger.isDebugEnabled()) {
            Logger.debug("ElasticSearch : Results -> " + Joiner.on(",").join(results));
        }
        long pageSize = 10;
        if (size > -1) {
            pageSize = size;
        }

        long pageCurrent = 1;
        if (from > 0) {
            pageCurrent = ((int) (from / pageSize)) + 1;
        }

        long pageNb;
        if (pageSize == 0) {
            pageNb = 1;
        } else {
            pageNb = (long) Math.ceil(new BigDecimal(count).divide(new BigDecimal(pageSize), 2, RoundingMode.HALF_UP).doubleValue());
        }

        return new IndexResults<>(count, pageSize, pageCurrent, pageNb, results, facetsResponse);
    }

}
TOP

Related Classes of com.codetroopers.play.elasticsearch.IndexQuery

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.