DATES-615 - Use annotated field name on repository order by clause.
Original PR: #298
This commit is contained in:
committed by
GitHub
parent
d1aa604fe5
commit
9e93dd08aa
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2019 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;
|
||||
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.data.elasticsearch.config.ElasticsearchConfigurationSupport;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchEntityMapper;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
|
||||
import org.springframework.data.elasticsearch.core.EntityMapper;
|
||||
|
||||
/**
|
||||
* configuration class for the classic ElasticsearchTemplate. Needs a {@link TestNodeResource} bean that should be set up in
|
||||
* the test as ClassRule and exported as bean.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
@Configuration
|
||||
public class ElasticsearchTestConfiguration extends ElasticsearchConfigurationSupport {
|
||||
|
||||
@Autowired private TestNodeResource testNodeResource;
|
||||
|
||||
@Bean
|
||||
public Client elasticsearchClient() {
|
||||
return testNodeResource.client();
|
||||
}
|
||||
|
||||
@Bean(name = { "elasticsearchOperations", "elasticsearchTemplate" })
|
||||
public ElasticsearchTemplate elasticsearchTemplate(Client elasticsearchClient, EntityMapper entityMapper) {
|
||||
return new ElasticsearchTemplate(elasticsearchClient, entityMapper);
|
||||
}
|
||||
|
||||
/*
|
||||
* need the ElasticsearchMapper, because some tests rely on @Field(name) being handled correctly
|
||||
*/
|
||||
@Bean
|
||||
@Override
|
||||
public EntityMapper entityMapper() {
|
||||
ElasticsearchEntityMapper entityMapper = new ElasticsearchEntityMapper(elasticsearchMappingContext(),
|
||||
new DefaultConversionService());
|
||||
entityMapper.setConversions(elasticsearchCustomConversions());
|
||||
|
||||
return entityMapper;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2019 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;
|
||||
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchEntityMapper;
|
||||
import org.springframework.data.elasticsearch.core.EntityMapper;
|
||||
|
||||
/**
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
@Configuration
|
||||
public class RestElasticsearchTestConfiguration extends AbstractElasticsearchConfiguration {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
public RestHighLevelClient elasticsearchClient() {
|
||||
return TestUtils.restHighLevelClient();
|
||||
}
|
||||
|
||||
/*
|
||||
* need the ElasticsearchMapper, because some tests rely on @Field(name) being handled correctly
|
||||
*/
|
||||
@Bean
|
||||
@Override
|
||||
public EntityMapper entityMapper() {
|
||||
ElasticsearchEntityMapper entityMapper = new ElasticsearchEntityMapper(elasticsearchMappingContext(),
|
||||
new DefaultConversionService());
|
||||
entityMapper.setConversions(elasticsearchCustomConversions());
|
||||
|
||||
return entityMapper;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2019 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;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.node.Node;
|
||||
import org.junit.rules.ExternalResource;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* JUnit4 Rule that sets up and tears down a local Elasticsearch node.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
public class TestNodeResource extends ExternalResource {
|
||||
|
||||
private static Node node;
|
||||
|
||||
@Override
|
||||
protected void before() throws Throwable {
|
||||
node = Utils.getNode();
|
||||
node.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void after() {
|
||||
if (node != null) {
|
||||
try {
|
||||
node.close();
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
public Client client() {
|
||||
Assert.notNull(node, "node is not initialized");
|
||||
return node.client();
|
||||
}
|
||||
}
|
||||
@@ -15,33 +15,42 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch;
|
||||
|
||||
import static java.util.Arrays.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.node.Node;
|
||||
import org.elasticsearch.node.NodeValidationException;
|
||||
import org.elasticsearch.transport.Netty4Plugin;
|
||||
|
||||
import org.springframework.data.elasticsearch.client.NodeClientFactoryBean;
|
||||
|
||||
/**
|
||||
* @author Mohsin Husen
|
||||
* @author Artur Konczak
|
||||
* @author Ilkang Na
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
public class Utils {
|
||||
|
||||
public static Client getNodeClient() throws NodeValidationException {
|
||||
|
||||
public static Node getNode() {
|
||||
String pathHome = "src/test/resources/test-home-dir";
|
||||
String pathData = "target/elasticsearchTestData";
|
||||
String clusterName = UUID.randomUUID().toString();
|
||||
|
||||
return new NodeClientFactoryBean.TestNode(Settings.builder().put("transport.type", "netty4")
|
||||
.put("http.type", "netty4").put("path.home", pathHome).put("path.data", pathData)
|
||||
.put("cluster.name", clusterName).put("node.max_local_storage_nodes", 100).build(), asList(Netty4Plugin.class))
|
||||
.start().client();
|
||||
return new NodeClientFactoryBean.TestNode( //
|
||||
Settings.builder() //
|
||||
.put("transport.type", "netty4") //
|
||||
.put("http.type", "netty4") //
|
||||
.put("path.home", pathHome) //
|
||||
.put("path.data", pathData) //
|
||||
.put("cluster.name", clusterName) //
|
||||
.put("node.max_local_storage_nodes", 100)//
|
||||
.build(), //
|
||||
Collections.singletonList(Netty4Plugin.class));
|
||||
}
|
||||
|
||||
public static Client getNodeClient() throws NodeValidationException {
|
||||
return getNode().start().client();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2019 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.repository.query.keywords;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.elasticsearch.ElasticsearchTestConfiguration;
|
||||
import org.springframework.data.elasticsearch.TestNodeResource;
|
||||
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
/**
|
||||
* {@link QueryKeywordsTests} using a Repository backed by an ElasticsearchTemplate.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
@ContextConfiguration(classes = { QueryKeywordsRepositoryTests.class, ElasticsearchTestConfiguration.class })
|
||||
@Configuration
|
||||
@EnableElasticsearchRepositories(considerNestedRepositories = true)
|
||||
public class QueryKeywordsRepositoryTests extends QueryKeywordsTests {
|
||||
|
||||
@ClassRule public static TestNodeResource testNodeResource = new TestNodeResource();
|
||||
|
||||
// needed by the ElasticsearchTestConfiguration.
|
||||
@Bean
|
||||
public TestNodeResource nodeResource() {
|
||||
return testNodeResource;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2019 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.repository.query.keywords;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.elasticsearch.RestElasticsearchTestConfiguration;
|
||||
import org.springframework.data.elasticsearch.TestNodeResource;
|
||||
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* {@link QueryKeywordsTests} using a Repository backed by an ElasticsearchRestTemplate.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
@ContextConfiguration(classes = { QueryKeywordsRestRepositoryTests.class, RestElasticsearchTestConfiguration.class })
|
||||
@Configuration
|
||||
@EnableElasticsearchRepositories(considerNestedRepositories = true)
|
||||
public class QueryKeywordsRestRepositoryTests extends QueryKeywordsTests {
|
||||
|
||||
@ClassRule public static TestNodeResource testNodeResource = new TestNodeResource();
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import lombok.Setter;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -35,36 +36,43 @@ import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
|
||||
import org.springframework.data.elasticsearch.utils.IndexInitializer;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* base class for query keyword tests. Implemented by subclasses using ElasticsearchClient and ElasticsearchRestClient
|
||||
* based repositories.
|
||||
*
|
||||
* @author Artur Konczak
|
||||
* @author Christoph Strobl
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration("classpath:/repository-query-keywords.xml")
|
||||
public class QueryKeywordsTests {
|
||||
abstract class QueryKeywordsTests {
|
||||
|
||||
@Autowired private ProductRepository repository;
|
||||
|
||||
@Autowired private ElasticsearchTemplate elasticsearchTemplate;
|
||||
@Autowired private ElasticsearchOperations elasticsearchTemplate;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
|
||||
IndexInitializer.init(elasticsearchTemplate, Product.class);
|
||||
|
||||
repository.saveAll(
|
||||
Arrays.asList(Product.builder().id("1").name("Sugar").text("Cane sugar").price(1.0f).available(false).build(),
|
||||
Product.builder().id("2").name("Sugar").text("Cane sugar").price(1.2f).available(true).build(),
|
||||
Product.builder().id("3").name("Sugar").text("Beet sugar").price(1.1f).available(true).build(),
|
||||
Product.builder().id("4").name("Salt").text("Rock salt").price(1.9f).available(true).build(),
|
||||
Product.builder().id("5").name("Salt").text("Sea salt").price(2.1f).available(false).build()));
|
||||
Product product1 = Product.builder().id("1").name("Sugar").text("Cane sugar").price(1.0f).available(false)
|
||||
.sortName("sort5").build();
|
||||
Product product2 = Product.builder().id("2").name("Sugar").text("Cane sugar").price(1.2f).available(true)
|
||||
.sortName("sort4").build();
|
||||
Product product3 = Product.builder().id("3").name("Sugar").text("Beet sugar").price(1.1f).available(true)
|
||||
.sortName("sort3").build();
|
||||
Product product4 = Product.builder().id("4").name("Salt").text("Rock salt").price(1.9f).available(true)
|
||||
.sortName("sort2").build();
|
||||
Product product5 = Product.builder().id("5").name("Salt").text("Sea salt").price(2.1f).available(false)
|
||||
.sortName("sort1").build();
|
||||
|
||||
repository.saveAll(Arrays.asList(product1, product2, product3, product4, product5));
|
||||
|
||||
elasticsearchTemplate.refresh(Product.class);
|
||||
}
|
||||
@@ -155,6 +163,40 @@ public class QueryKeywordsTests {
|
||||
assertThat(repository.findByPriceGreaterThanEqual(1.9f)).hasSize(2);
|
||||
}
|
||||
|
||||
@Test // DATAES-615
|
||||
public void shouldSupportSortOnStandardFieldWithCriteria() {
|
||||
List<String> sortedIds = repository.findAllByNameOrderByText("Salt").stream() //
|
||||
.map(it -> it.id).collect(Collectors.toList());
|
||||
|
||||
assertThat(sortedIds).containsExactly("4", "5");
|
||||
}
|
||||
|
||||
@Test // DATAES-615
|
||||
public void shouldSupportSortOnFieldWithCustomFieldNameWithCriteria() {
|
||||
|
||||
List<String> sortedIds = repository.findAllByNameOrderBySortName("Sugar").stream() //
|
||||
.map(it -> it.id).collect(Collectors.toList());
|
||||
|
||||
assertThat(sortedIds).containsExactly("3", "2", "1");
|
||||
}
|
||||
|
||||
@Test // DATAES-615
|
||||
public void shouldSupportSortOnStandardFieldWithoutCriteria() {
|
||||
List<String> sortedIds = repository.findAllByOrderByText().stream() //
|
||||
.map(it -> it.text).collect(Collectors.toList());
|
||||
|
||||
assertThat(sortedIds).containsExactly("Beet sugar", "Cane sugar", "Cane sugar", "Rock salt", "Sea salt");
|
||||
}
|
||||
|
||||
@Test // DATAES-615
|
||||
public void shouldSupportSortOnFieldWithCustomFieldNameWithoutCriteria() {
|
||||
|
||||
List<String> sortedIds = repository.findAllByOrderBySortName().stream() //
|
||||
.map(it -> it.id).collect(Collectors.toList());
|
||||
|
||||
assertThat(sortedIds).containsExactly("5", "4", "3", "2", "1");
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Mohsin Husen
|
||||
* @author Artur Konczak
|
||||
@@ -176,7 +218,7 @@ public class QueryKeywordsTests {
|
||||
|
||||
private String description;
|
||||
|
||||
private String text;
|
||||
@Field(type = FieldType.Keyword) private String text;
|
||||
|
||||
private List<String> categories;
|
||||
|
||||
@@ -191,12 +233,14 @@ public class QueryKeywordsTests {
|
||||
private String location;
|
||||
|
||||
private Date lastModified;
|
||||
|
||||
@Field(name = "sort-name", type = FieldType.Keyword) private String sortName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Created by akonczak on 04/09/15.
|
||||
*/
|
||||
interface ProductRepository extends PagingAndSortingRepository<Product, String> {
|
||||
interface ProductRepository extends ElasticsearchRepository<Product, String> {
|
||||
|
||||
List<Product> findByNameAndText(String name, String text);
|
||||
|
||||
@@ -227,6 +271,14 @@ public class QueryKeywordsTests {
|
||||
List<Product> findByPriceGreaterThanEqual(float v);
|
||||
|
||||
List<Product> findByIdNotIn(List<String> strings);
|
||||
|
||||
List<Product> findAllByNameOrderByText(String name);
|
||||
|
||||
List<Product> findAllByNameOrderBySortName(String name);
|
||||
|
||||
List<Product> findAllByOrderByText();
|
||||
|
||||
List<Product> findAllByOrderBySortName();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user