
com.liferay.search.experiences.internal.blueprint.aggregation.AggregationWrapperConverter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of com.liferay.search.experiences.service
Show all versions of com.liferay.search.experiences.service
Liferay Search Experiences Service
The newest version!
/**
* SPDX-FileCopyrightText: (c) 2000 Liferay, Inc. https://liferay.com
* SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
*/
package com.liferay.search.experiences.internal.blueprint.aggregation;
import com.liferay.petra.reflect.ReflectionUtil;
import com.liferay.petra.string.StringBundler;
import com.liferay.portal.kernel.json.JSONArray;
import com.liferay.portal.kernel.json.JSONObject;
import com.liferay.portal.kernel.json.JSONUtil;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.HashMapBuilder;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.search.aggregation.Aggregation;
import com.liferay.portal.search.aggregation.Aggregations;
import com.liferay.portal.search.aggregation.bucket.CollectionMode;
import com.liferay.portal.search.aggregation.bucket.DateHistogramAggregation;
import com.liferay.portal.search.aggregation.bucket.DateRangeAggregation;
import com.liferay.portal.search.aggregation.bucket.DiversifiedSamplerAggregation;
import com.liferay.portal.search.aggregation.bucket.FilterAggregation;
import com.liferay.portal.search.aggregation.bucket.FiltersAggregation;
import com.liferay.portal.search.aggregation.bucket.GeoDistanceAggregation;
import com.liferay.portal.search.aggregation.bucket.GeoHashGridAggregation;
import com.liferay.portal.search.aggregation.bucket.GlobalAggregation;
import com.liferay.portal.search.aggregation.bucket.HistogramAggregation;
import com.liferay.portal.search.aggregation.bucket.IncludeExcludeClause;
import com.liferay.portal.search.aggregation.bucket.MissingAggregation;
import com.liferay.portal.search.aggregation.bucket.NestedAggregation;
import com.liferay.portal.search.aggregation.bucket.Order;
import com.liferay.portal.search.aggregation.bucket.Range;
import com.liferay.portal.search.aggregation.bucket.RangeAggregation;
import com.liferay.portal.search.aggregation.bucket.ReverseNestedAggregation;
import com.liferay.portal.search.aggregation.bucket.SamplerAggregation;
import com.liferay.portal.search.aggregation.bucket.SignificantTermsAggregation;
import com.liferay.portal.search.aggregation.bucket.SignificantTextAggregation;
import com.liferay.portal.search.aggregation.bucket.TermsAggregation;
import com.liferay.portal.search.aggregation.metrics.AvgAggregation;
import com.liferay.portal.search.aggregation.metrics.CardinalityAggregation;
import com.liferay.portal.search.aggregation.metrics.ExtendedStatsAggregation;
import com.liferay.portal.search.aggregation.metrics.GeoBoundsAggregation;
import com.liferay.portal.search.aggregation.metrics.GeoCentroidAggregation;
import com.liferay.portal.search.aggregation.metrics.MaxAggregation;
import com.liferay.portal.search.aggregation.metrics.MinAggregation;
import com.liferay.portal.search.aggregation.metrics.PercentileRanksAggregation;
import com.liferay.portal.search.aggregation.metrics.PercentilesAggregation;
import com.liferay.portal.search.aggregation.metrics.PercentilesMethod;
import com.liferay.portal.search.aggregation.metrics.ScriptedMetricAggregation;
import com.liferay.portal.search.aggregation.metrics.StatsAggregation;
import com.liferay.portal.search.aggregation.metrics.SumAggregation;
import com.liferay.portal.search.aggregation.metrics.TopHitsAggregation;
import com.liferay.portal.search.aggregation.metrics.ValueCountAggregation;
import com.liferay.portal.search.aggregation.metrics.WeightedAvgAggregation;
import com.liferay.portal.search.aggregation.pipeline.AvgBucketPipelineAggregation;
import com.liferay.portal.search.aggregation.pipeline.BucketScriptPipelineAggregation;
import com.liferay.portal.search.aggregation.pipeline.BucketSelectorPipelineAggregation;
import com.liferay.portal.search.aggregation.pipeline.BucketSortPipelineAggregation;
import com.liferay.portal.search.aggregation.pipeline.CumulativeSumPipelineAggregation;
import com.liferay.portal.search.aggregation.pipeline.DerivativePipelineAggregation;
import com.liferay.portal.search.aggregation.pipeline.ExtendedStatsBucketPipelineAggregation;
import com.liferay.portal.search.aggregation.pipeline.GapPolicy;
import com.liferay.portal.search.aggregation.pipeline.MaxBucketPipelineAggregation;
import com.liferay.portal.search.aggregation.pipeline.MinBucketPipelineAggregation;
import com.liferay.portal.search.aggregation.pipeline.MovingFunctionPipelineAggregation;
import com.liferay.portal.search.aggregation.pipeline.PercentilesBucketPipelineAggregation;
import com.liferay.portal.search.aggregation.pipeline.PipelineAggregation;
import com.liferay.portal.search.aggregation.pipeline.SerialDiffPipelineAggregation;
import com.liferay.portal.search.aggregation.pipeline.StatsBucketPipelineAggregation;
import com.liferay.portal.search.aggregation.pipeline.SumBucketPipelineAggregation;
import com.liferay.portal.search.geolocation.DistanceUnit;
import com.liferay.portal.search.geolocation.GeoBuilders;
import com.liferay.portal.search.geolocation.GeoDistanceType;
import com.liferay.portal.search.query.Query;
import com.liferay.portal.search.script.Script;
import com.liferay.portal.search.script.ScriptField;
import com.liferay.portal.search.script.ScriptFieldBuilder;
import com.liferay.portal.search.script.Scripts;
import com.liferay.portal.search.significance.SignificanceHeuristic;
import com.liferay.portal.search.significance.SignificanceHeuristics;
import com.liferay.portal.search.sort.FieldSort;
import com.liferay.portal.search.sort.SortOrder;
import com.liferay.portal.search.sort.Sorts;
import com.liferay.search.experiences.internal.blueprint.highlight.HighlightConverter;
import com.liferay.search.experiences.internal.blueprint.query.QueryConverter;
import com.liferay.search.experiences.internal.blueprint.script.ScriptConverter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
/**
* @author Petteri Karttunen
*/
public class AggregationWrapperConverter {
public AggregationWrapperConverter(
Aggregations aggregations, GeoBuilders geoBuilders,
HighlightConverter highlightConverter, QueryConverter queryConverter,
ScriptConverter scriptConverter,
SignificanceHeuristics significanceHeuristics, Sorts sorts) {
_aggregations = aggregations;
_geoBuilders = geoBuilders;
_highlightConverter = highlightConverter;
_queryConverter = queryConverter;
_scriptConverter = scriptConverter;
_significanceHeuristics = significanceHeuristics;
_sorts = sorts;
// Bucket
_convertFunctions.putAll(
HashMapBuilder.put(
"date_histogram", this::_toDateHistogramAggregation
).put(
"date_range", this::_toDateRangeAggregation
).put(
"diversified_sampler", this::_toDiversifiedSamplerAggregation
).put(
"filter", this::_toFilterAggregation
).put(
"filters", this::_toFiltersAggregation
).put(
"geo_distance", this::_toGeoDistanceAggregation
).put(
"geohash_grid", this::_toGeoHashGridAggregation
).put(
"global", this::_toGlobalAggregation
).put(
"histogram", this::_toHistogramAggregation
).put(
"missing", this::_toMissingAggregation
).put(
"nested", this::_toNestedAggregation
).put(
"range", this::_toRangeAggregation
).put(
"reverse_nested", this::_toReverseNestedAggregation
).put(
"sampler", this::_toSamplerAggregation
).put(
"significant_terms", this::_toSignificantTermsAggregation
).put(
"significant_text", this::_toSignificantTextAggregation
).put(
"terms", this::_toTermsAggregation
).build());
// Metrics
_convertFunctions.putAll(
HashMapBuilder.put(
"avg", this::_toAvgAggregation
).put(
"cardinality", this::_toCardinalityAggregation
).put(
"extended_stats", this::_toExtendedStatsAggregation
).put(
"geo_bounds", this::_toGeoBoundsAggregation
).put(
"geo_centroid", this::_toGeoCentroidAggregation
).put(
"max", this::_toMaxAggregation
).put(
"min", this::_toMinAggregation
).put(
"percentile_ranks", this::_toPercentileRanksAggregation
).put(
"percentiles", this::_toPercentilesAggregation
).put(
"scripted_metric", this::_toScriptedMetricAggregation
).put(
"stats", this::_toStatsAggregation
).put(
"sum", this::_toSumAggregation
).put(
"top_hits", this::_toTopHitsAggregation
).put(
"value_count", this::_toValueCountAggregation
).put(
"weighted_avg", this::_toWeightedAvgAggregation
).build());
// Pipeline
_convertFunctions.putAll(
HashMapBuilder.put(
"avg_bucket", this::_toAvgBucketPipelineAggregation
).put(
"bucket_script", this::_toBucketScriptPipelineAggregation
).put(
"bucket_selector", this::_toBucketSelectorPipelineAggregation
).put(
"bucket_sort", this::_toBucketSortPipelineAggregation
).put(
"cumulative_sum", this::_toCumulativeSumPipelineAggregation
).put(
"derivative", this::_toDerivativePipelineAggregation
).put(
"extended_stats_bucket",
this::_toExtendedStatsBucketPipelineAggregation
).put(
"max_bucket", this::_toMaxBucketPipelineAggregation
).put(
"min_bucket", this::_toMinBucketPipelineAggregation
).put(
"moving_function", this::_toMovingFunctionPipelineAggregation
).put(
"percentiles_bucket",
this::_toPercentilesBucketPipelineAggregation
).put(
"serial_differencing", this::_toSerialDiffPipelineAggregation
).put(
"stats_bucket", this::_toStatsBucketPipelineAggregation
).put(
"sum_bucket", this::_toSumBucketPipelineAggregation
).build());
_scripts = scriptConverter.getScripts();
}
public AggregationWrapper toAggregationWrapper(
JSONObject jsonObject, String name, String type) {
ConvertFunction convertFunction = _convertFunctions.get(type);
if (convertFunction == null) {
throw new IllegalArgumentException("Unknown aggregation " + type);
}
try {
Object object = convertFunction.apply(jsonObject, name);
if (object == null) {
return null;
}
if (object instanceof Aggregation) {
return new AggregationWrapper((Aggregation)object);
}
else if (object instanceof PipelineAggregation) {
return new AggregationWrapper((PipelineAggregation)object);
}
throw new RuntimeException(
StringBundler.concat(
"JSON ", jsonObject, " converted to unexpected class ",
object.getClass()));
}
catch (Exception exception) {
return ReflectionUtil.throwException(exception);
}
}
@FunctionalInterface
public interface ConvertFunction {
public Object apply(JSONObject jsonObject, String name)
throws Exception;
}
private void _addBucketsPaths(
BiConsumer biConsumer, JSONObject jsonObject) {
Object object = jsonObject.get("buckets_path");
if ((object == null) || !(object instanceof JSONObject)) {
return;
}
JSONObject bucketsPathJSONObject = (JSONObject)object;
for (String key : bucketsPathJSONObject.keySet()) {
biConsumer.accept(key, bucketsPathJSONObject.getString(key));
}
}
private void _addOrders(Consumer consumer, JSONObject jsonObject) {
JSONObject orderJSONObject = jsonObject.getJSONObject("order");
if (orderJSONObject == null) {
return;
}
List orders = new ArrayList<>();
for (String key : orderJSONObject.keySet()) {
Order order = null;
boolean ascending = StringUtil.equalsIgnoreCase(
orderJSONObject.getString(key), "asc");
if (Order.COUNT_METRIC_NAME.equals(key)) {
order = Order.count(ascending);
}
else if (Order.KEY_METRIC_NAME.equals(key)) {
order = Order.key(ascending);
}
else {
order = new Order(key);
order.setAscending(ascending);
}
orders.add(order);
}
consumer.accept(orders.toArray(new Order[0]));
}
private void _addRange(Consumer consumer, JSONObject jsonObject) {
JSONArray rangesJSONArray = jsonObject.getJSONArray("ranges");
if (rangesJSONArray == null) {
return;
}
for (int i = 0; i < rangesJSONArray.length(); i++) {
JSONObject rangeJSONObject = rangesJSONArray.getJSONObject(i);
String key = rangeJSONObject.getString("key");
if (Validator.isNotNull(key)) {
consumer.accept(
new Range(
key, rangeJSONObject.getString("from", null),
rangeJSONObject.getString("to", null)));
}
else {
consumer.accept(
new Range(
rangeJSONObject.getString("from", null),
rangeJSONObject.getString("to", null)));
}
}
}
private SignificanceHeuristic _getSignificanceHeuristics(
JSONObject jsonObject) {
JSONObject chiSquareJSONObject = jsonObject.getJSONObject("chi_square");
if (chiSquareJSONObject != null) {
return _significanceHeuristics.chiSquare(
chiSquareJSONObject.getBoolean("background_is_superset", true),
chiSquareJSONObject.getBoolean("include_negatives", true));
}
JSONObject gndJSONObject = jsonObject.getJSONObject("gnd");
if (gndJSONObject != null) {
return _significanceHeuristics.gnd(
gndJSONObject.getBoolean("background_is_superset", true));
}
if (jsonObject.has("jlh")) {
return _significanceHeuristics.jlhScore();
}
JSONObject mutualInformationJSONObject = jsonObject.getJSONObject(
"mutual_information");
if (mutualInformationJSONObject != null) {
return _significanceHeuristics.mutualInformation(
mutualInformationJSONObject.getBoolean(
"background_is_superset", true),
mutualInformationJSONObject.getBoolean(
"include_negatives", true));
}
if (jsonObject.has("percentage")) {
return _significanceHeuristics.percentageScore();
}
JSONObject scriptHeuristicJSONObject = jsonObject.getJSONObject(
"script_heuristic");
if (scriptHeuristicJSONObject != null) {
Script script = _scriptConverter.toScript(
scriptHeuristicJSONObject);
return _significanceHeuristics.script(script);
}
return null;
}
private void _setBackgroundFilterQuery(
Consumer consumer, JSONObject jsonObject) {
JSONObject backgroundFilterJSONObject = jsonObject.getJSONObject(
"background_filter");
if (backgroundFilterJSONObject == null) {
return;
}
Query query = _queryConverter.toQuery(backgroundFilterJSONObject);
if (query == null) {
return;
}
consumer.accept(query);
}
private void _setBoolean(
Consumer consumer, JSONObject jsonObject, String key) {
if (!jsonObject.has(key)) {
return;
}
consumer.accept(jsonObject.getBoolean(key));
}
private void _setDouble(
Consumer consumer, JSONObject jsonObject, String key) {
if (!jsonObject.has(key)) {
return;
}
consumer.accept(jsonObject.getDouble(key));
}
private void _setGapPolicy(
Consumer consumer, JSONObject jsonObject) {
String gapPolicy = jsonObject.getString("gap_policy");
if (Validator.isNull(gapPolicy)) {
return;
}
consumer.accept(GapPolicy.valueOf(StringUtil.toUpperCase(gapPolicy)));
}
private void _setIncludeExcludeClause(
Consumer consumer, JSONObject jsonObject) {
Object excludeObject = jsonObject.get("exclude");
Object includeObject = jsonObject.get("include");
if ((excludeObject == null) && (includeObject == null)) {
return;
}
String[] excludedValues = null;
String excludeRegex = null;
String[] includedValues = null;
String includeRegex = null;
if (excludeObject != null) {
if (excludeObject instanceof JSONArray) {
excludedValues = JSONUtil.toStringArray(
(JSONArray)excludeObject);
}
else {
excludeRegex = GetterUtil.getString(excludeObject);
}
}
if (includeObject != null) {
if (includeObject instanceof JSONArray) {
includedValues = JSONUtil.toStringArray(
(JSONArray)includeObject);
}
else {
includeRegex = GetterUtil.getString(includeObject);
}
}
final String[] finalExcludedValues = excludedValues;
final String finalExcludeRegex = excludeRegex;
final String[] finalIncludedValues = includedValues;
final String finalIncludeRegex = includeRegex;
consumer.accept(
new IncludeExcludeClause() {
@Override
public String[] getExcludedValues() {
return finalExcludedValues;
}
@Override
public String getExcludeRegex() {
return finalExcludeRegex;
}
@Override
public String[] getIncludedValues() {
return finalIncludedValues;
}
@Override
public String getIncludeRegex() {
return finalIncludeRegex;
}
});
}
private void _setInteger(
Consumer consumer, JSONObject jsonObject, String key) {
if (!jsonObject.has(key)) {
return;
}
consumer.accept(jsonObject.getInt(key));
}
private void _setLong(
Consumer consumer, JSONObject jsonObject, String key) {
if (!jsonObject.has(key)) {
return;
}
consumer.accept(jsonObject.getLong(key));
}
private void _setObject(
Consumer