From fb9ccf7b449836b40d64c8576507111bd87b3803 Mon Sep 17 00:00:00 2001 From: Peter-Josef Meisch Date: Tue, 12 Dec 2023 18:58:34 +0100 Subject: [PATCH] Polishing. --- .../parser/ElasticsearchQueryCreator.java | 263 +++++++++--------- 1 file changed, 132 insertions(+), 131 deletions(-) diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/query/parser/ElasticsearchQueryCreator.java b/src/main/java/org/springframework/data/elasticsearch/repository/query/parser/ElasticsearchQueryCreator.java index d132dd117..d83020873 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/query/parser/ElasticsearchQueryCreator.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/query/parser/ElasticsearchQueryCreator.java @@ -15,8 +15,6 @@ */ package org.springframework.data.elasticsearch.repository.query.parser; -import java.util.Collection; -import java.util.Iterator; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.domain.Sort; import org.springframework.data.elasticsearch.core.geo.GeoBox; @@ -35,6 +33,9 @@ import org.springframework.data.repository.query.parser.Part; import org.springframework.data.repository.query.parser.PartTree; import org.springframework.lang.Nullable; +import java.util.Collection; +import java.util.Iterator; + /** * ElasticsearchQueryCreator * @@ -47,159 +48,159 @@ import org.springframework.lang.Nullable; */ public class ElasticsearchQueryCreator extends AbstractQueryCreator { - private final MappingContext context; + private final MappingContext context; - public ElasticsearchQueryCreator(PartTree tree, ParameterAccessor parameters, - MappingContext context) { - super(tree, parameters); - this.context = context; - } + public ElasticsearchQueryCreator(PartTree tree, ParameterAccessor parameters, + MappingContext context) { + super(tree, parameters); + this.context = context; + } - public ElasticsearchQueryCreator(PartTree tree, MappingContext context) { - super(tree); - this.context = context; - } + public ElasticsearchQueryCreator(PartTree tree, MappingContext context) { + super(tree); + this.context = context; + } - @Override - protected CriteriaQuery create(Part part, Iterator iterator) { - PersistentPropertyPath path = context.getPersistentPropertyPath( - part.getProperty()); - return new CriteriaQuery(from(part, - new Criteria(path.toDotPath(ElasticsearchPersistentProperty.QueryPropertyToFieldNameConverter.INSTANCE)), - iterator)); - } + @Override + protected CriteriaQuery create(Part part, Iterator iterator) { + PersistentPropertyPath path = context.getPersistentPropertyPath( + part.getProperty()); + return new CriteriaQuery(from(part, + new Criteria(path.toDotPath(ElasticsearchPersistentProperty.QueryPropertyToFieldNameConverter.INSTANCE)), + iterator)); + } - @Override - protected CriteriaQuery and(Part part, CriteriaQuery base, Iterator iterator) { - if (base == null) { - return create(part, iterator); - } - PersistentPropertyPath path = context.getPersistentPropertyPath( - part.getProperty()); - return base.addCriteria(from(part, - new Criteria(path.toDotPath(ElasticsearchPersistentProperty.QueryPropertyToFieldNameConverter.INSTANCE)), - iterator)); - } + @Override + protected CriteriaQuery and(Part part, CriteriaQuery base, Iterator iterator) { + if (base == null) { + return create(part, iterator); + } + PersistentPropertyPath path = context.getPersistentPropertyPath( + part.getProperty()); + return base.addCriteria(from(part, + new Criteria(path.toDotPath(ElasticsearchPersistentProperty.QueryPropertyToFieldNameConverter.INSTANCE)), + iterator)); + } - @Override - protected CriteriaQuery or(CriteriaQuery base, CriteriaQuery query) { - return new CriteriaQuery(base.getCriteria().or(query.getCriteria())); - } + @Override + protected CriteriaQuery or(CriteriaQuery base, CriteriaQuery query) { + return new CriteriaQuery(base.getCriteria().or(query.getCriteria())); + } - @Override - protected CriteriaQuery complete(@Nullable CriteriaQuery query, Sort sort) { + @Override + protected CriteriaQuery complete(@Nullable CriteriaQuery query, Sort sort) { - if (query == null) { - // this is the case in a findAllByOrderByField method, add empty criteria - query = new CriteriaQuery(new Criteria()); - } - return query.addSort(sort); - } + if (query == null) { + // this is the case in a findAllByOrderByField method, add empty criteria + query = new CriteriaQuery(new Criteria()); + } + return query.addSort(sort); + } - private Criteria from(Part part, Criteria criteria, Iterator parameters) { + private Criteria from(Part part, Criteria criteria, Iterator parameters) { - Part.Type type = part.getType(); + Part.Type type = part.getType(); - return switch (type) { - case TRUE -> criteria.is(true); - case FALSE -> criteria.is(false); - case NEGATING_SIMPLE_PROPERTY -> criteria.is(parameters.next()).not(); - case REGEX -> criteria.expression(parameters.next().toString()); - case LIKE, STARTING_WITH -> criteria.startsWith(parameters.next().toString()); - case ENDING_WITH -> criteria.endsWith(parameters.next().toString()); - case CONTAINING -> criteria.contains(parameters.next().toString()); - case GREATER_THAN -> criteria.greaterThan(parameters.next()); - case AFTER, GREATER_THAN_EQUAL -> criteria.greaterThanEqual(parameters.next()); - case LESS_THAN -> criteria.lessThan(parameters.next()); - case BEFORE, LESS_THAN_EQUAL -> criteria.lessThanEqual(parameters.next()); - case BETWEEN -> criteria.between(parameters.next(), parameters.next()); - case IN -> criteria.in(asArray(parameters.next())); - case NOT_IN -> criteria.notIn(asArray(parameters.next())); - case SIMPLE_PROPERTY, WITHIN -> this.within(part, criteria, parameters); - case NEAR -> this.near(criteria, parameters); - case EXISTS, IS_NOT_NULL -> criteria.exists(); - case IS_NULL -> criteria.not().exists(); - case IS_EMPTY -> criteria.empty(); - case IS_NOT_EMPTY -> criteria.notEmpty(); - default -> throw new InvalidDataAccessApiUsageException("Illegal criteria found '" + type + "'."); - }; - } + return switch (type) { + case TRUE -> criteria.is(true); + case FALSE -> criteria.is(false); + case NEGATING_SIMPLE_PROPERTY -> criteria.is(parameters.next()).not(); + case REGEX -> criteria.expression(parameters.next().toString()); + case LIKE, STARTING_WITH -> criteria.startsWith(parameters.next().toString()); + case ENDING_WITH -> criteria.endsWith(parameters.next().toString()); + case CONTAINING -> criteria.contains(parameters.next().toString()); + case GREATER_THAN -> criteria.greaterThan(parameters.next()); + case AFTER, GREATER_THAN_EQUAL -> criteria.greaterThanEqual(parameters.next()); + case LESS_THAN -> criteria.lessThan(parameters.next()); + case BEFORE, LESS_THAN_EQUAL -> criteria.lessThanEqual(parameters.next()); + case BETWEEN -> criteria.between(parameters.next(), parameters.next()); + case IN -> criteria.in(asArray(parameters.next())); + case NOT_IN -> criteria.notIn(asArray(parameters.next())); + case SIMPLE_PROPERTY, WITHIN -> within(part, criteria, parameters); + case NEAR -> near(criteria, parameters); + case EXISTS, IS_NOT_NULL -> criteria.exists(); + case IS_NULL -> criteria.not().exists(); + case IS_EMPTY -> criteria.empty(); + case IS_NOT_EMPTY -> criteria.notEmpty(); + default -> throw new InvalidDataAccessApiUsageException("Illegal criteria found '" + type + "'."); + }; + } - private Criteria within(Part part, Criteria criteria, Iterator parameters) { + private Criteria within(Part part, Criteria criteria, Iterator parameters) { - Object firstParameter = parameters.next(); - Object secondParameter; + Object firstParameter = parameters.next(); + Object secondParameter; - if (part.getType() == Part.Type.SIMPLE_PROPERTY) { - if (part.getProperty().getType() != GeoPoint.class) { - if (firstParameter != null) { - return criteria.is(firstParameter); - } else { - // searching for null is a must_not (exists) - return criteria.exists().not(); - } - } else { - // it means it's a simple find with exact geopoint matching (e.g. findByLocation) - // and because Elasticsearch does not have any kind of query with just a geopoint - // as argument we use a "geo distance" query with a distance of one meter. - secondParameter = ".001km"; - } - } else { - secondParameter = parameters.next(); - } + if (part.getType() == Part.Type.SIMPLE_PROPERTY) { + if (part.getProperty().getType() != GeoPoint.class) { + if (firstParameter != null) { + return criteria.is(firstParameter); + } else { + // searching for null is a must_not (exists) + return criteria.exists().not(); + } + } else { + // it means it's a simple find with exact geopoint matching (e.g. findByLocation) + // and because Elasticsearch does not have any kind of query with just a geopoint + // as argument we use a "geo distance" query with a distance of one meter. + secondParameter = ".001km"; + } + } else { + secondParameter = parameters.next(); + } - return doWithinIfPossible(criteria, firstParameter, secondParameter); - } + return doWithinIfPossible(criteria, firstParameter, secondParameter); + } - private Criteria near(Criteria criteria, Iterator parameters) { + private Criteria near(Criteria criteria, Iterator parameters) { - Object firstParameter = parameters.next(); + Object firstParameter = parameters.next(); - if (firstParameter instanceof GeoBox geoBox) { - return criteria.boundedBy(geoBox); - } + if (firstParameter instanceof GeoBox geoBox) { + return criteria.boundedBy(geoBox); + } - if (firstParameter instanceof Box box) { - return criteria.boundedBy(GeoBox.fromBox(box)); - } + if (firstParameter instanceof Box box) { + return criteria.boundedBy(GeoBox.fromBox(box)); + } - Object secondParameter = parameters.next(); + Object secondParameter = parameters.next(); - return doWithinIfPossible(criteria, firstParameter, secondParameter); - } + return doWithinIfPossible(criteria, firstParameter, secondParameter); + } - /** - * Do a within query if possible, otherwise return the criteria unchanged. - * - * @param criteria must not be {@literal null} - * @param firstParameter must not be {@literal null} - * @param secondParameter must not be {@literal null} - * @return the criteria with the within query applied if possible. - * @author Junghoon Ban - */ - private Criteria doWithinIfPossible(Criteria criteria, Object firstParameter, Object secondParameter) { + /** + * Do a within query if possible, otherwise return the criteria unchanged. + * + * @param criteria must not be {@literal null} + * @param firstParameter must not be {@literal null} + * @param secondParameter must not be {@literal null} + * @return the criteria with the within query applied if possible. + * @author Junghoon Ban + */ + private Criteria doWithinIfPossible(Criteria criteria, Object firstParameter, Object secondParameter) { - if (firstParameter instanceof GeoPoint geoPoint && secondParameter instanceof String string) { - return criteria.within(geoPoint, string); - } + if (firstParameter instanceof GeoPoint geoPoint && secondParameter instanceof String string) { + return criteria.within(geoPoint, string); + } - if (firstParameter instanceof Point point && secondParameter instanceof Distance distance) { - return criteria.within(point, distance); - } + if (firstParameter instanceof Point point && secondParameter instanceof Distance distance) { + return criteria.within(point, distance); + } - if (firstParameter instanceof String firstString && secondParameter instanceof String secondString) { - return criteria.within(firstString, secondString); - } + if (firstParameter instanceof String firstString && secondParameter instanceof String secondString) { + return criteria.within(firstString, secondString); + } - return criteria; - } + return criteria; + } - private Object[] asArray(Object o) { - if (o instanceof Collection) { - return ((Collection) o).toArray(); - } else if (o.getClass().isArray()) { - return (Object[]) o; - } - return new Object[] { o }; - } + private Object[] asArray(Object o) { + if (o instanceof Collection) { + return ((Collection) o).toArray(); + } else if (o.getClass().isArray()) { + return (Object[]) o; + } + return new Object[]{o}; + } }