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

net.guerlab.cloud.searchparams.elasticsearch.BoolQueryBuilderDefaultHandler Maven / Gradle / Ivy

/*
 * Copyright 2018-2024 guerlab.net and other contributors.
 *
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, Version 3 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.gnu.org/licenses/lgpl-3.0.html
 *
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.guerlab.cloud.searchparams.elasticsearch;

import java.time.temporal.Temporal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import java.util.function.Function;

import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.ChildScoreMode;
import co.elastic.clients.elasticsearch._types.query_dsl.NestedQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.json.JsonData;
import co.elastic.clients.util.ObjectBuilder;
import jakarta.annotation.Nullable;

import net.guerlab.cloud.searchparams.JsonField;
import net.guerlab.cloud.searchparams.OrderBys;
import net.guerlab.cloud.searchparams.SearchModelType;
import net.guerlab.cloud.searchparams.SearchParamsHandler;

/**
 * BoolQuery.Builder默认处理.
 *
 * @author guer
 */
public class BoolQueryBuilderDefaultHandler implements SearchParamsHandler {

	private static final List notTypes = Arrays.asList(
			SearchModelType.IS_NULL,
			SearchModelType.NOT_EQUAL_TO,
			SearchModelType.NOT_LIKE,
			SearchModelType.START_NOT_WITH,
			SearchModelType.END_NOT_WITH,
			SearchModelType.NOT_IN
	);

	private static TimeZone defaultTimeZone = TimeZone.getDefault();

	public static void setDefaultTimeZone(@Nullable TimeZone val) {
		if (val == null) {
			defaultTimeZone = TimeZone.getDefault();
		}
		else {
			defaultTimeZone = val;
		}
	}

	public static TimeZone getTimeZone() {
		return defaultTimeZone;
	}

	@Override
	public void setValue(Object object, String fieldName, String columnName, Object value, SearchModelType searchModelType,
			@Nullable String customSql, @Nullable JsonField jsonField) {
		if (value instanceof OrderBys) {
			return;
		}

		BoolQuery.Builder builder = (BoolQuery.Builder) object;

		boolean isNested = columnName.contains(".");
		List paths = new ArrayList<>();
		if (isNested) {
			String[] pathArray = columnName.split("\\.");
			paths.addAll(Arrays.stream(Arrays.copyOfRange(pathArray, 0, pathArray.length - 1)).toList());
		}

		Function> fn;
		if (searchModelType == SearchModelType.IS_NULL || searchModelType == SearchModelType.IS_NOT_NULL) {
			fn = m -> m.exists(t -> t.field(columnName));
		}
		else if (searchModelType == SearchModelType.LIKE || searchModelType == SearchModelType.NOT_LIKE) {
			fn = m -> m.wildcard(q -> q.field(columnName).value("*" + value + "*"));
		}
		else if (searchModelType == SearchModelType.START_WITH || searchModelType == SearchModelType.START_NOT_WITH) {
			fn = m -> m.wildcard(q -> q.field(columnName).value(value + "*"));
		}
		else if (searchModelType == SearchModelType.END_WITH || searchModelType == SearchModelType.END_NOT_WITH) {
			fn = m -> m.wildcard(q -> q.field(columnName).value("*" + value));
		}
		else if (searchModelType == SearchModelType.GREATER_THAN ||
				searchModelType == SearchModelType.GREATER_THAN_OR_EQUAL_TO ||
				searchModelType == SearchModelType.LESS_THAN ||
				searchModelType == SearchModelType.LESS_THAN_OR_EQUAL_TO) {
			fn = m -> m.range(r -> {
				r.field(columnName);
				if (value instanceof Date || value instanceof Temporal) {
					r.timeZone(getTimeZone().getID());
				}

				if (searchModelType == SearchModelType.GREATER_THAN) {
					r.gt(JsonData.of(value));
				}
				if (searchModelType == SearchModelType.GREATER_THAN_OR_EQUAL_TO) {
					r.gte(JsonData.of(value));
				}
				else if (searchModelType == SearchModelType.LESS_THAN) {
					r.lt(JsonData.of(value));
				}
				else if (searchModelType == SearchModelType.LESS_THAN_OR_EQUAL_TO) {
					r.lte(JsonData.of(value));
				}
				return r;
			});
		}
		else if (searchModelType == SearchModelType.IN || searchModelType == SearchModelType.NOT_IN) {
			List fieldValues = new ArrayList<>();
			if (value instanceof Iterable collection) {
				for (Object o : collection) {
					fieldValues.add(FieldValue.of(o.toString()));
				}
			}
			else if (value.getClass().isArray()) {
				Object[] array = (Object[]) value;
				for (Object o : array) {
					fieldValues.add(FieldValue.of(o.toString()));
				}
			}
			if (!fieldValues.isEmpty()) {
				fn = m -> m.terms(q -> q.field(columnName).terms(b -> b.value(fieldValues)));
			}
			else {
				fn = m -> m.match(q -> q.field(columnName).query(value.toString()));
			}
		}
		else {
			if (value instanceof String str) {
				fn = m -> m.term(t -> t.field(columnName + ".keyword").value(str));
			}
			else {
				fn = m -> m.term(t -> t.field(columnName).value(String.valueOf(value)));
			}
		}

		if (!paths.isEmpty()) {
			List nestedQueryBuilders = new ArrayList<>(paths.size());

			for (int i = 0; i < paths.size(); i++) {
				String allPath = String.join(".", paths.subList(0, i + 1));
				NestedQuery.Builder nestedQueryBuilder = new NestedQuery.Builder();
				nestedQueryBuilder.path(allPath);
				nestedQueryBuilder.scoreMode(ChildScoreMode.Max);
				nestedQueryBuilders.add(nestedQueryBuilder);
			}

			int size = nestedQueryBuilders.size() - 1;

			NestedQuery.Builder firstBuilder = nestedQueryBuilders.get(0);
			NestedQuery.Builder lastBuilder = nestedQueryBuilders.get(size);
			lastBuilder.query(fn);

			for (int i = 0; i <= size; i++) {
				NestedQuery.Builder currentBuilder = nestedQueryBuilders.get(i);
				NestedQuery.Builder childBuilder = i < size ? nestedQueryBuilders.get(i + 1) : null;

				if (childBuilder != null) {
					currentBuilder.query(q -> q.nested(n -> childBuilder));
				}
			}

			if (notTypes.contains(searchModelType)) {
				builder.mustNot(q -> q.nested(n -> firstBuilder));
			}
			else {
				builder.must(q -> q.nested(n -> firstBuilder));
			}
		}
		else {
			if (notTypes.contains(searchModelType)) {
				builder.mustNot(fn);
			}
			else {
				builder.must(fn);
			}
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy