/*
* Copyright 2012-2015 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
*
* http://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.solr.repository.query;
import java.lang.reflect.Method;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.AbstractRepositoryMetadata;
import org.springframework.data.solr.core.DefaultQueryParser;
import org.springframework.data.solr.core.QueryParser;
import org.springframework.data.solr.core.SolrOperations;
import org.springframework.data.solr.repository.ProductBean;
import org.springframework.data.solr.repository.Query;
import org.springframework.data.solr.server.SolrClientFactory;
/**
* @author Christoph Strobl
* @author Oliver Gierke
*/
@RunWith(MockitoJUnitRunner.class)
public class StringBasedSolrQueryTests {
private @Mock SolrOperations solrOperationsMock;
private @Mock SolrEntityInformationCreator entityInformationCreatorMock;
private @Mock SolrClientFactory solrClientFactoryMock;
private RepositoryMetadata metadata = AbstractRepositoryMetadata.getMetadata(SampleRepository.class);
private ProjectionFactory factory = new SpelAwareProxyProjectionFactory();
private QueryParser queryParser;
@Before
public void setUp() {
this.queryParser = new DefaultQueryParser();
}
@Test
public void testQueryCreationSingleProperty() throws NoSuchMethodException, SecurityException {
Method method = SampleRepository.class.getMethod("findByText", String.class);
SolrQueryMethod queryMethod = new SolrQueryMethod(method, metadata, factory, entityInformationCreatorMock);
StringBasedSolrQuery solrQuery = new StringBasedSolrQuery(queryMethod, solrOperationsMock);
org.springframework.data.solr.core.query.Query query = solrQuery
.createQuery(new SolrParametersParameterAccessor(queryMethod, new Object[] { "j73x73r" }));
Assert.assertEquals("textGeneral:j73x73r", queryParser.getQueryString(query));
}
@Test
public void testQueryCreationWithNegativeProperty() throws NoSuchMethodException, SecurityException {
Method method = SampleRepository.class.getMethod("findByPopularityAndPrice", Integer.class, Float.class);
SolrQueryMethod queryMethod = new SolrQueryMethod(method, metadata, factory, entityInformationCreatorMock);
StringBasedSolrQuery solrQuery = new StringBasedSolrQuery(queryMethod, solrOperationsMock);
org.springframework.data.solr.core.query.Query query = solrQuery.createQuery(
new SolrParametersParameterAccessor(queryMethod, new Object[] { Integer.valueOf(-1), Float.valueOf(-2f) }));
Assert.assertEquals("popularity:\\-1 AND price:\\-2.0", queryParser.getQueryString(query));
}
@Test
public void testQueryCreationMultiyProperty() throws NoSuchMethodException, SecurityException {
Method method = SampleRepository.class.getMethod("findByPopularityAndPrice", Integer.class, Float.class);
SolrQueryMethod queryMethod = new SolrQueryMethod(method, metadata, factory, entityInformationCreatorMock);
StringBasedSolrQuery solrQuery = new StringBasedSolrQuery(queryMethod, solrOperationsMock);
org.springframework.data.solr.core.query.Query query = solrQuery.createQuery(
new SolrParametersParameterAccessor(queryMethod, new Object[] { Integer.valueOf(1), Float.valueOf(2f) }));
Assert.assertEquals("popularity:1 AND price:2.0", queryParser.getQueryString(query));
}
@Test
public void testQueryCreationWithNullProperty() throws NoSuchMethodException, SecurityException {
Method method = SampleRepository.class.getMethod("findByText", String.class);
SolrQueryMethod queryMethod = new SolrQueryMethod(method, metadata, factory, entityInformationCreatorMock);
StringBasedSolrQuery solrQuery = new StringBasedSolrQuery(queryMethod, solrOperationsMock);
org.springframework.data.solr.core.query.Query query = solrQuery
.createQuery(new SolrParametersParameterAccessor(queryMethod, new Object[] { null }));
Assert.assertEquals("textGeneral:null", queryParser.getQueryString(query));
}
@Test
public void testWithPointProperty() throws NoSuchMethodException, SecurityException {
Method method = SampleRepository.class.getMethod("findByLocationNear", Point.class, Distance.class);
SolrQueryMethod queryMethod = new SolrQueryMethod(method, metadata, factory, entityInformationCreatorMock);
StringBasedSolrQuery solrQuery = new StringBasedSolrQuery(queryMethod, solrOperationsMock);
org.springframework.data.solr.core.query.Query query = solrQuery.createQuery(new SolrParametersParameterAccessor(
queryMethod, new Object[] { new Point(48.303056, 14.290556), new Distance(5) }));
Assert.assertEquals("{!geofilt pt=48.303056,14.290556 sfield=store d=5.0}", queryParser.getQueryString(query));
}
@Test
public void testWithPointPropertyWhereDistanceIsInMiles() throws NoSuchMethodException, SecurityException {
Method method = SampleRepository.class.getMethod("findByLocationNear", Point.class, Distance.class);
SolrQueryMethod queryMethod = new SolrQueryMethod(method, metadata, factory, entityInformationCreatorMock);
StringBasedSolrQuery solrQuery = new StringBasedSolrQuery(queryMethod, solrOperationsMock);
org.springframework.data.solr.core.query.Query query = solrQuery.createQuery(new SolrParametersParameterAccessor(
queryMethod, new Object[] { new Point(48.303056, 14.290556), new Distance(1, Metrics.MILES) }));
Assert.assertEquals("{!geofilt pt=48.303056,14.290556 sfield=store d=1.609344}", queryParser.getQueryString(query));
}
@Test
public void testWithProjectionOnSingleField() throws NoSuchMethodException, SecurityException {
Method method = SampleRepository.class.getMethod("findByNameProjectionOnPopularity", String.class);
SolrQueryMethod queryMethod = new SolrQueryMethod(method, metadata, factory, entityInformationCreatorMock);
StringBasedSolrQuery solrQuery = new StringBasedSolrQuery(queryMethod, solrOperationsMock);
org.springframework.data.solr.core.query.Query query = solrQuery
.createQuery(new SolrParametersParameterAccessor(queryMethod, new Object[] { "christoph" }));
Assert.assertEquals("name:christoph*", queryParser.getQueryString(query));
Assert.assertEquals(1, query.getProjectionOnFields().size());
Assert.assertEquals("popularity", query.getProjectionOnFields().get(0).getName());
}
@Test
public void testWithProjectionOnMultipleFields() throws NoSuchMethodException, SecurityException {
Method method = SampleRepository.class.getMethod("findByNameProjectionOnPopularityAndPrice", String.class);
SolrQueryMethod queryMethod = new SolrQueryMethod(method, metadata, factory, entityInformationCreatorMock);
StringBasedSolrQuery solrQuery = new StringBasedSolrQuery(queryMethod, solrOperationsMock);
org.springframework.data.solr.core.query.Query query = solrQuery
.createQuery(new SolrParametersParameterAccessor(queryMethod, new Object[] { "strobl" }));
Assert.assertEquals("name:strobl*", queryParser.getQueryString(query));
Assert.assertEquals(2, query.getProjectionOnFields().size());
Assert.assertEquals("popularity", query.getProjectionOnFields().get(0).getName());
Assert.assertEquals("price", query.getProjectionOnFields().get(1).getName());
}
@Test
public void testWithSort() throws NoSuchMethodException, SecurityException {
Method method = SampleRepository.class.getMethod("findByNameWithSort", String.class, Sort.class);
SolrQueryMethod queryMethod = new SolrQueryMethod(method, metadata, factory, entityInformationCreatorMock);
StringBasedSolrQuery solrQuery = new StringBasedSolrQuery(queryMethod, solrOperationsMock);
Sort sort = new Sort(Direction.DESC, "popularity", "price");
org.springframework.data.solr.core.query.Query query = solrQuery
.createQuery(new SolrParametersParameterAccessor(queryMethod, new Object[] { "spring", sort }));
Assert.assertEquals("name:spring", queryParser.getQueryString(query));
Assert.assertEquals(sort, query.getSort());
}
@Test
public void testWithSortInPageable() throws NoSuchMethodException, SecurityException {
Method method = SampleRepository.class.getMethod("findByNameWithSortInPageable", String.class, Pageable.class);
SolrQueryMethod queryMethod = new SolrQueryMethod(method, metadata, factory, entityInformationCreatorMock);
StringBasedSolrQuery solrQuery = new StringBasedSolrQuery(queryMethod, solrOperationsMock);
Sort sort = new Sort(Direction.DESC, "popularity", "price");
org.springframework.data.solr.core.query.Query query = solrQuery.createQuery(
new SolrParametersParameterAccessor(queryMethod, new Object[] { "spring", new PageRequest(0, 10, sort) }));
Assert.assertEquals("name:spring", queryParser.getQueryString(query));
Assert.assertEquals(sort, query.getSort());
}
private interface SampleRepository extends Repository<ProductBean, String> {
@Query("textGeneral:?0")
ProductBean findByText(String text);
@Query("popularity:?0 AND price:?1")
ProductBean findByPopularityAndPrice(Integer popularity, Float price);
@Query("{!geofilt pt=?0 sfield=store d=?1}")
ProductBean findByLocationNear(Point location, Distance distace);
@Query(value = "name:?0*", fields = "popularity")
ProductBean findByNameProjectionOnPopularity(String name);
@Query(value = "name:?0*", fields = { "popularity", "price" })
ProductBean findByNameProjectionOnPopularityAndPrice(String name);
@Query(value = "name:?0")
ProductBean findByNameWithSort(String name, Sort sort);
@Query(value = "name:?0")
Page<ProductBean> findByNameWithSortInPageable(String name, Pageable pageable);
}
}