DATAES-734 - Add Sort implementation that allows geo distance sorts.

Original PR: #382
This commit is contained in:
Peter-Josef Meisch
2020-01-23 18:03:37 +01:00
committed by GitHub
parent bf13ed919f
commit 37f15853c0
8 changed files with 325 additions and 12 deletions

View File

@@ -36,7 +36,7 @@ import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
/**
* Tests for the mapping of {@link CriteriaQuery} by a
* {@link org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter}. In the same package as
* {@link CriteriaQueryProcessor} as this is needed to get the String represenation to assert.
* {@link CriteriaQueryProcessor} as this is needed to get the String representation to assert.
*
* @author Peter-Josef Meisch
*/
@@ -59,8 +59,8 @@ public class CriteriaQueryMappingTests {
void shouldMapNamesAndConvertValuesInCriteriaQuery() throws JSONException {
// use POJO properties and types in the query building
CriteriaQuery criteriaQuery = new CriteriaQuery(
new Criteria("birthDate").between(LocalDate.of(1989, 11, 9), LocalDate.of(1990, 11, 9)).or("birthDate").is(LocalDate.of(2019, 12, 28)));
CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("birthDate")
.between(LocalDate.of(1989, 11, 9), LocalDate.of(1990, 11, 9)).or("birthDate").is(LocalDate.of(2019, 12, 28)));
// mapped field name and converted parameter
String expected = '{' + //

View File

@@ -0,0 +1,111 @@
/*
* Copyright 2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.elasticsearch.core;
import static org.skyscreamer.jsonassert.JSONAssert.*;
import java.util.Collections;
import org.json.JSONException;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.data.elasticsearch.core.query.GeoDistanceOrder;
/**
* @author Peter-Josef Meisch
*/
class RequestFactoryTest {
private static RequestFactory requestFactory;
private static MappingElasticsearchConverter converter;
@BeforeAll
static void setUpAll() {
SimpleElasticsearchMappingContext mappingContext = new SimpleElasticsearchMappingContext();
mappingContext.setInitialEntitySet(Collections.singleton(Person.class));
mappingContext.afterPropertiesSet();
converter = new MappingElasticsearchConverter(mappingContext, new GenericConversionService());
converter.afterPropertiesSet();
requestFactory = new RequestFactory((converter));
}
@Test // FPI-734
void shouldBuildSearchWithGeoSortSort() throws JSONException {
CriteriaQuery query = new CriteriaQuery(new Criteria("lastName").is("Smith"));
Sort sort = Sort.by(new GeoDistanceOrder("location", new GeoPoint(49.0, 8.4)));
query.addSort(sort);
converter.updateQuery(query, Person.class);
String expected = '{' + //
" \"query\": {" + //
" \"bool\": {" + //
" \"must\": [" + //
" {" + //
" \"query_string\": {" + //
" \"query\": \"Smith\"," + //
" \"fields\": [" + //
" \"first-name^1.0\"" + //
" ]" + //
" }" + //
" }" + //
" ]" + //
" }" + //
" }," + //
" \"sort\": [" + //
" {" + //
" \"_geo_distance\": {" + //
" \"current-location\": [" + //
" {" + //
" \"lat\": 49.0," + //
" \"lon\": 8.4" + //
" }" + //
" ]," + //
" \"unit\": \"m\"," + //
" \"distance_type\": \"arc\"," + //
" \"order\": \"asc\"," + //
" \"mode\": \"min\"," + //
" \"ignore_unmapped\": false" + //
" }" + //
" }" + //
" ]" + //
'}';
String searchRequest = requestFactory.searchRequest(query, Person.class, IndexCoordinates.of("persons")).source()
.toString();
assertEquals(expected, searchRequest, false);
}
static class Person {
@Id String id;
@Field(name = "last-name") String lastName;
@Field(name = "current-location") GeoPoint location;
}
}

View File

@@ -54,6 +54,7 @@ import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.geo.GeoBox;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.elasticsearch.core.query.GeoDistanceOrder;
import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.data.elasticsearch.utils.IndexInitializer;
@@ -1441,6 +1442,40 @@ public abstract class CustomMethodRepositoryBaseTests {
assertThat(searchHit.getHighlightField("type")).hasSize(1).contains("<em>abc</em>");
}
@Test // DATAES-734
void shouldUseGeoSortParameter() {
GeoPoint munich = new GeoPoint(48.137154, 11.5761247);
GeoPoint berlin = new GeoPoint(52.520008, 13.404954);
GeoPoint vienna = new GeoPoint(48.20849, 16.37208);
GeoPoint oslo = new GeoPoint(59.9127, 10.7461);
List<SampleEntity> entities = new ArrayList<>();
SampleEntity entity1 = new SampleEntity();
entity1.setId("berlin");
entity1.setLocation(berlin);
entities.add(entity1);
SampleEntity entity2 = new SampleEntity();
entity2.setId("vienna");
entity2.setLocation(vienna);
entities.add(entity2);
SampleEntity entity3 = new SampleEntity();
entity3.setId("oslo");
entity3.setLocation(oslo);
entities.add(entity3);
repository.saveAll(entities);
SearchHits<SampleEntity> searchHits = repository.searchBy(Sort.by(new GeoDistanceOrder("location", munich)));
assertThat(searchHits.getTotalHits()).isEqualTo(3);
assertThat(searchHits.getSearchHit(0).getId()).isEqualTo("vienna");
assertThat(searchHits.getSearchHit(1).getId()).isEqualTo("berlin");
assertThat(searchHits.getSearchHit(2).getId()).isEqualTo("oslo");
}
private List<SampleEntity> createSampleEntities(String type, int numberOfEntities) {
List<SampleEntity> entities = new ArrayList<>();
@@ -1588,6 +1623,7 @@ public abstract class CustomMethodRepositoryBaseTests {
Stream<SearchHit<SampleEntity>> readByMessage(String message);
SearchHits<SampleEntity> searchBy(Sort sort);
}
/**