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

io.searchbox.core.SearchResult Maven / Gradle / Ivy

There is a newer version: 6.3.1
Show newest version
package io.searchbox.core;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import io.searchbox.client.JestResult;
import io.searchbox.cloning.CloneUtils;
import io.searchbox.core.search.aggregation.MetricAggregation;
import io.searchbox.core.search.aggregation.RootAggregation;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;

import java.util.*;

/**
 * @author cihat keser
 */
public class SearchResult extends JestResult {

    public static final String EXPLANATION_KEY = "_explanation";
    public static final String HIGHLIGHT_KEY = "highlight";
    public static final String SORT_KEY = "sort";
    public static final String[] PATH_TO_TOTAL = "hits/total".split("/");
    public static final String[] PATH_TO_MAX_SCORE = "hits/max_score".split("/");

    public SearchResult(SearchResult searchResult) {
        super(searchResult);
    }

    public SearchResult(Gson gson) {
        super(gson);
    }

    @Override
    @Deprecated
    public  T getSourceAsObject(Class clazz) {
        return super.getSourceAsObject(clazz);
    }

    @Override
    @Deprecated
    public  List getSourceAsObjectList(Class type) {
        return super.getSourceAsObjectList(type);
    }

    public  Hit getFirstHit(Class sourceType) {
        return getFirstHit(sourceType, Void.class);
    }

    public  Hit getFirstHit(Class sourceType, Class explanationType) {
        Hit hit = null;

        List> hits = getHits(sourceType, explanationType, true);
        if (!hits.isEmpty()) {
            hit = hits.get(0);
        }

        return hit;
    }

    public  List> getHits(Class sourceType) {
        return getHits(sourceType, Void.class);
    }

    public  List> getHits(Class sourceType, Class explanationType) {
        return getHits(sourceType, explanationType, false);
    }

    protected  List> getHits(Class sourceType, Class explanationType, boolean returnSingle) {
        List> sourceList = new ArrayList>();

        if (jsonObject != null) {
            String[] keys = getKeys();
            if (keys != null) { // keys would never be null in a standard search scenario (i.e.: unless search class is overwritten)
                String sourceKey = keys[keys.length - 1];
                JsonElement obj = jsonObject.get(keys[0]);
                for (int i = 1; i < keys.length - 1; i++) {
                    obj = ((JsonObject) obj).get(keys[i]);
                }

                if (obj.isJsonObject()) {
                    sourceList.add(extractHit(sourceType, explanationType, obj, sourceKey));
                } else if (obj.isJsonArray()) {
                    for (JsonElement hitElement : obj.getAsJsonArray()) {
                        sourceList.add(extractHit(sourceType, explanationType, hitElement, sourceKey));
                        if (returnSingle) break;
                    }
                }
            }
        }

        return sourceList;
    }

    protected  Hit extractHit(Class sourceType, Class explanationType, JsonElement hitElement, String sourceKey) {
        Hit hit = null;

        if (hitElement.isJsonObject()) {
            JsonObject hitObject = hitElement.getAsJsonObject();
            JsonObject source = hitObject.getAsJsonObject(sourceKey);

            if (source != null) {
                String index = hitObject.get("_index").getAsString();
                String type = hitObject.get("_type").getAsString();

                Double score = null;
                if (hitObject.has("_score") && !hitObject.get("_score").isJsonNull()) {
                    score = hitObject.get("_score").getAsDouble();
                }

                JsonElement explanation = hitObject.get(EXPLANATION_KEY);
                Map> highlight = extractHighlight(hitObject.getAsJsonObject(HIGHLIGHT_KEY));
                List sort = extractSort(hitObject.getAsJsonArray(SORT_KEY));

                JsonObject clonedSource = null;
                for (MetaField metaField : META_FIELDS) {
                    JsonElement metaElement = hitObject.get(metaField.esFieldName);
                    if (metaElement != null) {
                        if (clonedSource == null) {
                            clonedSource = (JsonObject) CloneUtils.deepClone(source);
                        }
                        clonedSource.add(metaField.internalFieldName, metaElement);
                    }
                }
                if (clonedSource != null) {
                    source = clonedSource;
                }

                hit = new Hit(
                        sourceType,
                        source,
                        explanationType,
                        explanation,
                        highlight,
                        sort,
                        index,
                        type,
                        score
                );
            }
        }

        return hit;
    }

    protected List extractSort(JsonArray sort) {
        if (sort == null) {
            return null;
        }

        List retval = new ArrayList(sort.size());
        for (JsonElement sortValue : sort) {
            retval.add(sortValue.isJsonNull() ? "" : sortValue.getAsString());
        }
        return retval;
    }

    protected Map> extractHighlight(JsonObject highlight) {
        Map> retval = null;

        if (highlight != null) {
            Set> highlightSet = highlight.entrySet();
            retval = new HashMap>(highlightSet.size());

            for (Map.Entry entry : highlightSet) {
                List fragments = new ArrayList();
                for (JsonElement element : entry.getValue().getAsJsonArray()) {
                    fragments.add(element.getAsString());
                }
                retval.put(entry.getKey(), fragments);
            }
        }

        return retval;
    }

    public Integer getTotal() {
        Integer total = null;
        JsonElement obj = getPath(PATH_TO_TOTAL);
        if (obj != null) total = obj.getAsInt();
        return total;
    }

    public Float getMaxScore() {
        Float maxScore = null;
        JsonElement obj = getPath(PATH_TO_MAX_SCORE);
        if (obj != null) maxScore = obj.getAsFloat();
        return maxScore;
    }

    protected JsonElement getPath(String[] path) {
        JsonElement retval = null;
        if (jsonObject != null) {
            JsonElement obj = jsonObject;
            for (String component : path) {
                if (obj == null) break;
                obj = ((JsonObject) obj).get(component);
            }
            retval = obj;
        }
        return retval;
    }

    public MetricAggregation getAggregations() {
        final String rootAggrgationName = "aggs";
        if (jsonObject == null) return new RootAggregation(rootAggrgationName, new JsonObject());
        if (jsonObject.has("aggregations"))
            return new RootAggregation(rootAggrgationName, jsonObject.getAsJsonObject("aggregations"));
        if (jsonObject.has("aggs")) return new RootAggregation(rootAggrgationName, jsonObject.getAsJsonObject("aggs"));

        return new RootAggregation(rootAggrgationName, new JsonObject());
    }

    /**
     * Immutable class representing a search hit.
     *
     * @param  type of source
     * @param  type of explanation
     * @author cihat keser
     */
    public class Hit {

        public final T source;
        public final K explanation;
        public final Map> highlight;
        public final List sort;
        public final String index;
        public final String type;
        public final Double score;

        public Hit(Class sourceType, JsonElement source) {
            this(sourceType, source, null, null);
        }

        public Hit(Class sourceType, JsonElement source, Class explanationType, JsonElement explanation) {
            this(sourceType, source, explanationType, explanation, null, null);
        }

        public Hit(Class sourceType, JsonElement source, Class explanationType, JsonElement explanation,
                   Map> highlight, List sort) {
            this(sourceType, source, explanationType, explanation, highlight, sort, null, null, null);
        }

        public Hit(Class sourceType, JsonElement source, Class explanationType, JsonElement explanation,
                   Map> highlight, List sort, String index, String type, Double score) {
            if (source == null) {
                this.source = null;
            } else {
                this.source = createSourceObject(source, sourceType);
            }
            if (explanation == null) {
                this.explanation = null;
            } else {
                this.explanation = createSourceObject(explanation, explanationType);
            }
            this.highlight = highlight;
            this.sort = sort;

            this.index = index;
            this.type = type;
            this.score = score;
        }

        public Hit(T source) {
            this(source, null, null, null);
        }

        public Hit(T source, K explanation) {
            this(source, explanation, null, null);
        }

        public Hit(T source, K explanation, Map> highlight, List sort) {
            this(source, explanation, highlight, sort, null, null, null);
        }

        public Hit(T source, K explanation, Map> highlight, List sort, String index, String type, Double score) {
            this.source = source;
            this.explanation = explanation;
            this.highlight = highlight;
            this.sort = sort;

            this.index = index;
            this.type = type;
            this.score = score;
        }

        @Override
        public int hashCode() {
            return new HashCodeBuilder()
                    .append(source)
                    .append(explanation)
                    .append(highlight)
                    .append(sort)
                    .toHashCode();
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null) {
                return false;
            }
            if (obj == this) {
                return true;
            }
            if (obj.getClass() != getClass()) {
                return false;
            }

            Hit rhs = (Hit) obj;
            return new EqualsBuilder()
                    .append(source, rhs.source)
                    .append(explanation, rhs.explanation)
                    .append(highlight, rhs.highlight)
                    .append(sort, rhs.sort)
                    .isEquals();
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy