Compare commits

...

8 Commits

Author SHA1 Message Date
Spring Buildmaster
a05507c505 DATAES-212 - Release version 1.3.1.RELEASE (Gosling SR1). 2015-11-15 05:41:17 -08:00
Oliver Gierke
0273d593a3 DATAES-212 - Prepare 1.3.1.RELEASE (Gosling SR1). 2015-11-15 14:06:54 +01:00
Oliver Gierke
33707d1228 DATAES-212 - Updated changelog. 2015-11-15 14:06:49 +01:00
Oliver Gierke
3fe4f15828 DATAES-202 - Updated changelog. 2015-10-14 13:57:54 +02:00
Artur Konczak
1c1b124d6e DATAES-193 - After release cleanups. 2015-09-28 11:51:26 +01:00
Kevin Leturc
11e2d11b5b DATAES-200 - BACKPORT from master - Set persistent entity index and type in query when no indices/types are set. 2015-09-27 20:12:01 +01:00
Artur Konczak
7db077c2c6 DATAES-171 - BACKPORT from master - added support for missing query keywords 2015-09-27 20:10:48 +01:00
Artur Konczak
e6d698e250 DATAES-193 - Prepare next development iteration. 2015-09-27 20:04:50 +01:00
12 changed files with 380 additions and 151 deletions

13
pom.xml
View File

@ -4,12 +4,12 @@
<groupId>org.springframework.data</groupId> <groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId> <artifactId>spring-data-elasticsearch</artifactId>
<version>1.3.0.RELEASE</version> <version>1.3.1.RELEASE</version>
<parent> <parent>
<groupId>org.springframework.data.build</groupId> <groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId> <artifactId>spring-data-parent</artifactId>
<version>1.7.0.RELEASE</version> <version>1.7.1.RELEASE</version>
<relativePath>../spring-data-build/parent/pom.xml</relativePath> <relativePath>../spring-data-build/parent/pom.xml</relativePath>
</parent> </parent>
@ -24,7 +24,7 @@
<commonscollections>3.2.1</commonscollections> <commonscollections>3.2.1</commonscollections>
<commonslang>2.6</commonslang> <commonslang>2.6</commonslang>
<elasticsearch>1.5.2</elasticsearch> <elasticsearch>1.5.2</elasticsearch>
<springdata.commons>1.11.0.RELEASE</springdata.commons> <springdata.commons>1.11.1.RELEASE</springdata.commons>
</properties> </properties>
@ -121,6 +121,13 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.4</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -24,10 +24,11 @@ import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import org.apache.lucene.queryparser.flexible.core.util.StringUtils; import org.apache.lucene.queryparser.flexible.core.util.StringUtils;
import org.elasticsearch.index.query.*; import org.elasticsearch.index.query.BoolQueryBuilder;
import org.springframework.data.elasticsearch.core.geo.GeoPoint; import org.elasticsearch.index.query.BoostableQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
import org.springframework.data.elasticsearch.core.query.Criteria; import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.geo.Point;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
@ -36,6 +37,7 @@ import org.springframework.util.Assert;
* @author Rizwan Idrees * @author Rizwan Idrees
* @author Mohsin Husen * @author Mohsin Husen
* @author Franck Marchand * @author Franck Marchand
* @author Artur Konczak
*/ */
class CriteriaQueryProcessor { class CriteriaQueryProcessor {
@ -49,11 +51,19 @@ class CriteriaQueryProcessor {
List<QueryBuilder> mustQueryBuilderList = new LinkedList<QueryBuilder>(); List<QueryBuilder> mustQueryBuilderList = new LinkedList<QueryBuilder>();
ListIterator<Criteria> chainIterator = criteria.getCriteriaChain().listIterator(); ListIterator<Criteria> chainIterator = criteria.getCriteriaChain().listIterator();
QueryBuilder firstQuery = null;
boolean negateFirstQuery = false;
while (chainIterator.hasNext()) { while (chainIterator.hasNext()) {
Criteria chainedCriteria = chainIterator.next(); Criteria chainedCriteria = chainIterator.next();
QueryBuilder queryFragmentForCriteria = createQueryFragmentForCriteria(chainedCriteria); QueryBuilder queryFragmentForCriteria = createQueryFragmentForCriteria(chainedCriteria);
if (queryFragmentForCriteria != null) { if (queryFragmentForCriteria != null) {
if (firstQuery == null) {
firstQuery = queryFragmentForCriteria;
negateFirstQuery = chainedCriteria.isNegating();
continue;
}
if (chainedCriteria.isOr()) { if (chainedCriteria.isOr()) {
shouldQueryBuilderList.add(queryFragmentForCriteria); shouldQueryBuilderList.add(queryFragmentForCriteria);
} else if (chainedCriteria.isNegating()) { } else if (chainedCriteria.isNegating()) {
@ -64,6 +74,18 @@ class CriteriaQueryProcessor {
} }
} }
if (firstQuery != null) {
if (!shouldQueryBuilderList.isEmpty() && mustNotQueryBuilderList.isEmpty() && mustQueryBuilderList.isEmpty()) {
shouldQueryBuilderList.add(0, firstQuery);
} else {
if (negateFirstQuery) {
mustNotQueryBuilderList.add(0, firstQuery);
} else {
mustQueryBuilderList.add(0, firstQuery);
}
}
}
BoolQueryBuilder query = null; BoolQueryBuilder query = null;
if (!shouldQueryBuilderList.isEmpty() || !mustNotQueryBuilderList.isEmpty() || !mustQueryBuilderList.isEmpty()) { if (!shouldQueryBuilderList.isEmpty() || !mustNotQueryBuilderList.isEmpty() || !mustQueryBuilderList.isEmpty()) {
@ -98,12 +120,12 @@ class CriteriaQueryProcessor {
if (singeEntryCriteria) { if (singeEntryCriteria) {
Criteria.CriteriaEntry entry = it.next(); Criteria.CriteriaEntry entry = it.next();
query = processCriteriaEntry(entry.getKey(), entry.getValue(), fieldName); query = processCriteriaEntry(entry, fieldName);
} else { } else {
query = boolQuery(); query = boolQuery();
while (it.hasNext()) { while (it.hasNext()) {
Criteria.CriteriaEntry entry = it.next(); Criteria.CriteriaEntry entry = it.next();
((BoolQueryBuilder) query).must(processCriteriaEntry(entry.getKey(), entry.getValue(), fieldName)); ((BoolQueryBuilder) query).must(processCriteriaEntry(entry, fieldName));
} }
} }
@ -112,14 +134,18 @@ class CriteriaQueryProcessor {
} }
private QueryBuilder processCriteriaEntry(OperationKey key, Object value, String fieldName) { private QueryBuilder processCriteriaEntry(Criteria.CriteriaEntry entry,/* OperationKey key, Object value,*/ String fieldName) {
Object value = entry.getValue();
if (value == null) { if (value == null) {
return null; return null;
} }
OperationKey key = entry.getKey();
QueryBuilder query = null; QueryBuilder query = null;
String searchText = StringUtils.toString(value); String searchText = StringUtils.toString(value);
Iterable<Object> collection = null;
switch (key) { switch (key) {
case EQUALS: case EQUALS:
query = queryString(searchText).field(fieldName).defaultOperator(QueryStringQueryBuilder.Operator.AND); query = queryString(searchText).field(fieldName).defaultOperator(QueryStringQueryBuilder.Operator.AND);
@ -134,24 +160,42 @@ class CriteriaQueryProcessor {
query = queryString("*" + searchText).field(fieldName).analyzeWildcard(true); query = queryString("*" + searchText).field(fieldName).analyzeWildcard(true);
break; break;
case EXPRESSION: case EXPRESSION:
query = queryString((String) value).field(fieldName); query = queryString(searchText).field(fieldName);
break;
case LESS_EQUAL:
query = rangeQuery(fieldName).lte(value);
break;
case GREATER_EQUAL:
query = rangeQuery(fieldName).gte(value);
break; break;
case BETWEEN: case BETWEEN:
Object[] ranges = (Object[]) value; Object[] ranges = (Object[]) value;
query = rangeQuery(fieldName).from(ranges[0]).to(ranges[1]); query = rangeQuery(fieldName).from(ranges[0]).to(ranges[1]);
break; break;
case LESS:
query = rangeQuery(fieldName).lt(value);
break;
case GREATER:
query = rangeQuery(fieldName).gt(value);
break;
case FUZZY: case FUZZY:
query = fuzzyQuery(fieldName, (String) value); query = fuzzyQuery(fieldName, searchText);
break; break;
case IN: case IN:
query = boolQuery(); query = boolQuery();
Iterable<Object> collection = (Iterable<Object>) value; collection = (Iterable<Object>) value;
for (Object item : collection) { for (Object item : collection) {
((BoolQueryBuilder) query).should(queryString((String) item).field(fieldName)); ((BoolQueryBuilder) query).should(queryString(item.toString()).field(fieldName));
}
break;
case NOT_IN:
query = boolQuery();
collection = (Iterable<Object>) value;
for (Object item : collection) {
((BoolQueryBuilder) query).mustNot(queryString(item.toString()).field(fieldName));
} }
break; break;
} }
return query; return query;
} }

View File

@ -15,6 +15,21 @@
*/ */
package org.springframework.data.elasticsearch.core; package org.springframework.data.elasticsearch.core;
import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
import static org.apache.commons.lang.StringUtils.*;
import static org.elasticsearch.action.search.SearchType.*;
import static org.elasticsearch.client.Requests.*;
import static org.elasticsearch.cluster.metadata.AliasAction.Type.*;
import static org.elasticsearch.common.collect.Sets.*;
import static org.elasticsearch.index.VersionType.*;
import static org.springframework.data.elasticsearch.core.MappingBuilder.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.util.*;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.elasticsearch.action.ListenableActionFuture; import org.elasticsearch.action.ListenableActionFuture;
import org.elasticsearch.action.admin.cluster.state.ClusterStateRequest; import org.elasticsearch.action.admin.cluster.state.ClusterStateRequest;
@ -81,23 +96,6 @@ import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.util.CloseableIterator; import org.springframework.data.util.CloseableIterator;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.util.*;
import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
import static org.apache.commons.lang.StringUtils.isBlank;
import static org.apache.commons.lang.StringUtils.isNotBlank;
import static org.elasticsearch.action.search.SearchType.SCAN;
import static org.elasticsearch.client.Requests.indicesExistsRequest;
import static org.elasticsearch.client.Requests.refreshRequest;
import static org.elasticsearch.cluster.metadata.AliasAction.Type.ADD;
import static org.elasticsearch.common.collect.Sets.newHashSet;
import static org.elasticsearch.index.VersionType.EXTERNAL;
import static org.springframework.data.elasticsearch.core.MappingBuilder.buildMapping;
/** /**
* ElasticsearchTemplate * ElasticsearchTemplate
* *
@ -314,6 +312,9 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
if (elasticsearchFilter != null) if (elasticsearchFilter != null)
searchRequestBuilder.setPostFilter(elasticsearchFilter); searchRequestBuilder.setPostFilter(elasticsearchFilter);
if (logger.isDebugEnabled()) {
logger.debug("doSearch query:\n" + searchRequestBuilder.toString());
}
SearchResponse response = getSearchResponse(searchRequestBuilder SearchResponse response = getSearchResponse(searchRequestBuilder
.execute()); .execute());
@ -334,6 +335,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
@Override @Override
public <T> CloseableIterator<T> stream(CriteriaQuery query, Class<T> clazz) { public <T> CloseableIterator<T> stream(CriteriaQuery query, Class<T> clazz) {
final long scrollTimeInMillis = TimeValue.timeValueMinutes(1).millis(); final long scrollTimeInMillis = TimeValue.timeValueMinutes(1).millis();
setPersistentEntityIndexAndType(query, clazz);
final String initScrollId = scan(query, scrollTimeInMillis, false); final String initScrollId = scan(query, scrollTimeInMillis, false);
return doStream(initScrollId, scrollTimeInMillis, clazz, resultsMapper); return doStream(initScrollId, scrollTimeInMillis, clazz, resultsMapper);
} }
@ -346,6 +348,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
@Override @Override
public <T> CloseableIterator<T> stream(SearchQuery query, final Class<T> clazz, final SearchResultMapper mapper) { public <T> CloseableIterator<T> stream(SearchQuery query, final Class<T> clazz, final SearchResultMapper mapper) {
final long scrollTimeInMillis = TimeValue.timeValueMinutes(1).millis(); final long scrollTimeInMillis = TimeValue.timeValueMinutes(1).millis();
setPersistentEntityIndexAndType(query, clazz);
final String initScrollId = scan(query, scrollTimeInMillis, false); final String initScrollId = scan(query, scrollTimeInMillis, false);
return doStream(initScrollId, scrollTimeInMillis, clazz, mapper); return doStream(initScrollId, scrollTimeInMillis, clazz, mapper);
} }
@ -401,7 +404,6 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
} }
throw new NoSuchElementException(); throw new NoSuchElementException();
} }
}; };
} }
@ -536,7 +538,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
Assert.notNull(query.getUpdateRequest(), "No IndexRequest define for Query"); Assert.notNull(query.getUpdateRequest(), "No IndexRequest define for Query");
UpdateRequestBuilder updateRequestBuilder = client.prepareUpdate(indexName, type, query.getId()); UpdateRequestBuilder updateRequestBuilder = client.prepareUpdate(indexName, type, query.getId());
if(query.getUpdateRequest().script() == null) { if (query.getUpdateRequest().script() == null) {
// doc // doc
if (query.DoUpsert()) { if (query.DoUpsert()) {
updateRequestBuilder.setDocAsUpsert(true) updateRequestBuilder.setDocAsUpsert(true)
@ -896,12 +898,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
} }
private <T> SearchRequestBuilder prepareSearch(Query query, Class<T> clazz) { private <T> SearchRequestBuilder prepareSearch(Query query, Class<T> clazz) {
if (query.getIndices().isEmpty()) { setPersistentEntityIndexAndType(query, clazz);
query.addIndices(retrieveIndexNameFromPersistentEntity(clazz));
}
if (query.getTypes().isEmpty()) {
query.addTypes(retrieveTypeFromPersistentEntity(clazz));
}
return prepareSearch(query); return prepareSearch(query);
} }
@ -1063,6 +1060,15 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
} }
} }
private void setPersistentEntityIndexAndType(Query query, Class clazz) {
if (query.getIndices().isEmpty()) {
query.addIndices(retrieveIndexNameFromPersistentEntity(clazz));
}
if (query.getTypes().isEmpty()) {
query.addTypes(retrieveTypeFromPersistentEntity(clazz));
}
}
private String[] retrieveIndexNameFromPersistentEntity(Class clazz) { private String[] retrieveIndexNameFromPersistentEntity(Class clazz) {
if (clazz != null) { if (clazz != null) {
return new String[]{getPersistentEntityFor(clazz).getIndexName()}; return new String[]{getPersistentEntityFor(clazz).getIndexName()};

View File

@ -35,6 +35,17 @@ import org.springframework.util.Assert;
*/ */
public class Criteria { public class Criteria {
@Override
public String toString() {
return "Criteria{" +
"field=" + field.getName() +
", boost=" + boost +
", negating=" + negating +
", queryCriteria=" + StringUtils.join(queryCriteria, '|') +
", filterCriteria=" + StringUtils.join(filterCriteria, '|') +
'}';
}
public static final String WILDCARD = "*"; public static final String WILDCARD = "*";
public static final String CRITERIA_VALUE_SEPERATOR = " "; public static final String CRITERIA_VALUE_SEPERATOR = " ";
@ -71,7 +82,6 @@ public class Criteria {
public Criteria(Field field) { public Criteria(Field field) {
Assert.notNull(field, "Field for criteria must not be null"); Assert.notNull(field, "Field for criteria must not be null");
Assert.hasText(field.getName(), "Field.name for criteria must not be null/empty"); Assert.hasText(field.getName(), "Field.name for criteria must not be null/empty");
this.criteriaChain.add(this); this.criteriaChain.add(this);
this.field = field; this.field = field;
} }
@ -304,7 +314,18 @@ public class Criteria {
* @return * @return
*/ */
public Criteria lessThanEqual(Object upperBound) { public Criteria lessThanEqual(Object upperBound) {
between(null, upperBound); if (upperBound == null) {
throw new InvalidDataAccessApiUsageException("UpperBound can't be null");
}
queryCriteria.add(new CriteriaEntry(OperationKey.LESS_EQUAL, upperBound));
return this;
}
public Criteria lessThan(Object upperBound) {
if (upperBound == null) {
throw new InvalidDataAccessApiUsageException("UpperBound can't be null");
}
queryCriteria.add(new CriteriaEntry(OperationKey.LESS, upperBound));
return this; return this;
} }
@ -315,7 +336,18 @@ public class Criteria {
* @return * @return
*/ */
public Criteria greaterThanEqual(Object lowerBound) { public Criteria greaterThanEqual(Object lowerBound) {
between(lowerBound, null); if (lowerBound == null) {
throw new InvalidDataAccessApiUsageException("LowerBound can't be null");
}
queryCriteria.add(new CriteriaEntry(OperationKey.GREATER_EQUAL, lowerBound));
return this;
}
public Criteria greaterThan(Object lowerBound) {
if (lowerBound == null) {
throw new InvalidDataAccessApiUsageException("LowerBound can't be null");
}
queryCriteria.add(new CriteriaEntry(OperationKey.GREATER, lowerBound));
return this; return this;
} }
@ -326,12 +358,7 @@ public class Criteria {
* @return * @return
*/ */
public Criteria in(Object... values) { public Criteria in(Object... values) {
if (values.length == 0 || (values.length > 1 && values[1] instanceof Collection)) { return in(toCollection(values));
throw new InvalidDataAccessApiUsageException("At least one element "
+ (values.length > 0 ? ("of argument of type " + values[1].getClass().getName()) : "")
+ " has to be present.");
}
return in(Arrays.asList(values));
} }
/** /**
@ -346,6 +373,25 @@ public class Criteria {
return this; return this;
} }
private List<Object> toCollection(Object... values) {
if (values.length == 0 || (values.length > 1 && values[1] instanceof Collection)) {
throw new InvalidDataAccessApiUsageException("At least one element "
+ (values.length > 0 ? ("of argument of type " + values[1].getClass().getName()) : "")
+ " has to be present.");
}
return Arrays.asList(values);
}
public Criteria notIn(Object... values) {
return notIn(toCollection(values));
}
public Criteria notIn(Iterable<?> values) {
Assert.notNull(values, "Collection of 'NotIn' values must not be null");
queryCriteria.add(new CriteriaEntry(OperationKey.NOT_IN, values));
return this;
}
/** /**
* Creates new CriteriaEntry for {@code location WITHIN distance} * Creates new CriteriaEntry for {@code location WITHIN distance}
* *
@ -522,7 +568,7 @@ public class Criteria {
} }
public enum OperationKey { public enum OperationKey {
EQUALS, CONTAINS, STARTS_WITH, ENDS_WITH, EXPRESSION, BETWEEN, FUZZY, IN, WITHIN, BBOX, NEAR; EQUALS, CONTAINS, STARTS_WITH, ENDS_WITH, EXPRESSION, BETWEEN, FUZZY, IN, NOT_IN, WITHIN, BBOX, NEAR, LESS, LESS_EQUAL, GREATER, GREATER_EQUAL;
} }
public static class CriteriaEntry { public static class CriteriaEntry {
@ -542,5 +588,13 @@ public class Criteria {
public Object getValue() { public Object getValue() {
return value; return value;
} }
@Override
public String toString() {
return "CriteriaEntry{" +
"key=" + key +
", value=" + value +
'}';
}
} }
} }

View File

@ -41,6 +41,7 @@ import org.springframework.data.repository.query.parser.PartTree;
* @author Rizwan Idrees * @author Rizwan Idrees
* @author Mohsin Husen * @author Mohsin Husen
* @author Franck Marchand * @author Franck Marchand
* @author Artur Konczak
*/ */
public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuery, CriteriaQuery> { public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuery, CriteriaQuery> {
@ -112,12 +113,14 @@ public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuer
return criteria.endsWith(parameters.next().toString()); return criteria.endsWith(parameters.next().toString());
case CONTAINING: case CONTAINING:
return criteria.contains(parameters.next().toString()); return criteria.contains(parameters.next().toString());
case AFTER:
case GREATER_THAN: case GREATER_THAN:
return criteria.greaterThan(parameters.next());
case AFTER:
case GREATER_THAN_EQUAL: case GREATER_THAN_EQUAL:
return criteria.greaterThanEqual(parameters.next()); return criteria.greaterThanEqual(parameters.next());
case BEFORE:
case LESS_THAN: case LESS_THAN:
return criteria.lessThan(parameters.next());
case BEFORE:
case LESS_THAN_EQUAL: case LESS_THAN_EQUAL:
return criteria.lessThanEqual(parameters.next()); return criteria.lessThanEqual(parameters.next());
case BETWEEN: case BETWEEN:
@ -125,7 +128,7 @@ public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuer
case IN: case IN:
return criteria.in(asArray(parameters.next())); return criteria.in(asArray(parameters.next()));
case NOT_IN: case NOT_IN:
return criteria.in(asArray(parameters.next())).not(); return criteria.notIn(asArray(parameters.next()));
case SIMPLE_PROPERTY: case SIMPLE_PROPERTY:
case WITHIN: { case WITHIN: {
Object firstParameter = parameters.next(); Object firstParameter = parameters.next();

View File

@ -1,6 +1,16 @@
Spring Data Elasticsearch Changelog Spring Data Elasticsearch Changelog
=================================== ===================================
Changes in version 1.3.1.RELEASE (2015-11-15)
---------------------------------------------
* DATAES-212 - Release 1.3.1 (Gosling).
Changes in version 1.1.4.RELEASE (2015-10-14)
---------------------------------------------
* DATAES-202 - Release 1.1.4 (Evans).
Changes in version 1.3.0.RELEASE (2015-09-01) Changes in version 1.3.0.RELEASE (2015-09-01)
--------------------------------------------- ---------------------------------------------
* DATAES-193 - Release 1.3 GA (Gosling). * DATAES-193 - Release 1.3 GA (Gosling).

View File

@ -1,4 +1,4 @@
Spring Data Elasticsearch 1.3 GA Spring Data Elasticsearch 1.3.1
Copyright (c) [2013-2015] Pivotal Software, Inc. Copyright (c) [2013-2015] Pivotal Software, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License"). This product is licensed to you under the Apache License, Version 2.0 (the "License").

View File

@ -18,12 +18,21 @@ package org.springframework.data.elasticsearch.entities;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import lombok.*;
import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
/** /**
* @author Mohsin Husen * @author Mohsin Husen
* @author Artur Konczak
*/ */
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Document(indexName = "test-product-index", type = "test-product-type", indexStoreType = "memory", shards = 1, replicas = 0, refreshInterval = "-1") @Document(indexName = "test-product-index", type = "test-product-type", indexStoreType = "memory", shards = 1, replicas = 0, refreshInterval = "-1")
public class Product { public class Product {
@ -42,6 +51,7 @@ public class Product {
private Float weight; private Float weight;
@Field(type = FieldType.Float)
private Float price; private Float price;
private Integer popularity; private Integer popularity;
@ -52,93 +62,6 @@ public class Product {
private Date lastModified; private Date lastModified;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public List<String> getTitle() {
return title;
}
public void setTitle(List<String> title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public List<String> getCategories() {
return categories;
}
public void setCategories(List<String> categories) {
this.categories = categories;
}
public Float getWeight() {
return weight;
}
public void setWeight(Float weight) {
this.weight = weight;
}
public Float getPrice() {
return price;
}
public void setPrice(Float price) {
this.price = price;
}
public Integer getPopularity() {
return popularity;
}
public void setPopularity(Integer popularity) {
this.popularity = popularity;
}
public boolean isAvailable() {
return available;
}
public void setAvailable(boolean available) {
this.available = available;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public Date getLastModified() {
return lastModified;
}
public void setLastModified(Date lastModified) {
this.lastModified = lastModified;
}
@Override @Override
public int hashCode() { public int hashCode() {
@ -166,12 +89,4 @@ public class Product {
} }
return true; return true;
} }
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
} }

View File

@ -122,7 +122,7 @@ public class CustomMethodRepositoryTests {
SampleEntity sampleEntity = new SampleEntity(); SampleEntity sampleEntity = new SampleEntity();
sampleEntity.setId(documentId); sampleEntity.setId(documentId);
sampleEntity.setType("test"); sampleEntity.setType("test");
sampleEntity.setRate(10); sampleEntity.setRate(9);
sampleEntity.setMessage("some message"); sampleEntity.setMessage("some message");
repository.save(sampleEntity); repository.save(sampleEntity);
@ -753,7 +753,7 @@ public class CustomMethodRepositoryTests {
SampleEntity sampleEntity = new SampleEntity(); SampleEntity sampleEntity = new SampleEntity();
sampleEntity.setId(documentId); sampleEntity.setId(documentId);
sampleEntity.setType("test"); sampleEntity.setType("test");
sampleEntity.setRate(10); sampleEntity.setRate(9);
sampleEntity.setMessage("some message"); sampleEntity.setMessage("some message");
repository.save(sampleEntity); repository.save(sampleEntity);

View File

@ -0,0 +1,43 @@
package org.springframework.data.elasticsearch.repositories.query;
import java.util.List;
import org.springframework.data.elasticsearch.entities.Product;
import org.springframework.data.repository.PagingAndSortingRepository;
/**
* Created by akonczak on 04/09/15.
*/
public interface ProductRepository extends PagingAndSortingRepository<Product, String> {
public List<Product> findByNameAndText(String name, String text);
public List<Product> findByNameAndPrice(String name, Float price);
public List<Product> findByNameOrText(String name, String text);
public List<Product> findByNameOrPrice(String name, Float price);
public List<Product> findByAvailableTrue();
public List<Product> findByAvailableFalse();
public List<Product> findByPriceIn(List<Float> floats);
public List<Product> findByPriceNotIn(List<Float> floats);
public List<Product> findByPriceNot(float v);
public List<Product> findByPriceBetween(float v, float v1);
public List<Product> findByPriceLessThan(float v);
public List<Product> findByPriceLessThanEqual(float v);
public List<Product> findByPriceGreaterThan(float v);
public List<Product> findByPriceGreaterThanEqual(float v);
public List<Product> findByIdNotIn(List<String> strings);
}

View File

@ -0,0 +1,129 @@
package org.springframework.data.elasticsearch.repository.support;
import static org.hamcrest.core.Is.*;
import static org.junit.Assert.*;
import java.util.Arrays;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.entities.Product;
import org.springframework.data.elasticsearch.repositories.query.ProductRepository;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Artur Konczak
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/repository-query-support.xml")
public class QueryKeywordsTest {
@Autowired
private ProductRepository repository;
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Before
public void before() {
elasticsearchTemplate.deleteIndex(Product.class);
elasticsearchTemplate.createIndex(Product.class);
elasticsearchTemplate.putMapping(Product.class);
elasticsearchTemplate.refresh(Product.class, true);
repository.save(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()));
elasticsearchTemplate.refresh(Product.class, true);
}
@Test
public void shouldSupportAND() {
//given
//when
//then
assertThat(repository.findByNameAndText("Sugar", "Cane sugar").size(), is(2));
assertThat(repository.findByNameAndPrice("Sugar", 1.1f).size(), is(1));
}
@Test
public void shouldSupportOR() {
//given
//when
//then
assertThat(repository.findByNameOrPrice("Sugar", 1.9f).size(), is(4));
assertThat(repository.findByNameOrText("Salt", "Beet sugar").size(), is(3));
}
@Test
public void shouldSupportTrueAndFalse() {
//given
//when
//then
assertThat(repository.findByAvailableTrue().size(), is(3));
assertThat(repository.findByAvailableFalse().size(), is(2));
}
@Test
public void shouldSupportInAndNotInAndNot() {
//given
//when
//then
assertThat(repository.findByPriceIn(Arrays.asList(1.2f, 1.1f)).size(), is(2));
assertThat(repository.findByPriceNotIn(Arrays.asList(1.2f, 1.1f)).size(), is(3));
assertThat(repository.findByPriceNot(1.2f).size(), is(4));
}
/*
DATAES-171
*/
@Test
public void shouldWorkWithNotIn() {
//given
//when
//then
assertThat(repository.findByIdNotIn(Arrays.asList("2", "3")).size(), is(3));
}
@Test
public void shouldSupportBetween() {
//given
//when
//then
assertThat(repository.findByPriceBetween(1.0f, 2.0f).size(), is(4));
}
@Test
public void shouldSupportLessThanAndGreaterThan() {
//given
//when
//then
assertThat(repository.findByPriceLessThan(1.1f).size(), is(1));
assertThat(repository.findByPriceLessThanEqual(1.1f).size(), is(2));
assertThat(repository.findByPriceGreaterThan(1.9f).size(), is(1));
assertThat(repository.findByPriceGreaterThanEqual(1.9f).size(), is(2));
}
}

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:elasticsearch="http://www.springframework.org/schema/data/elasticsearch"
xsi:schemaLocation="http://www.springframework.org/schema/data/elasticsearch http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<import resource="infrastructure.xml"/>
<bean name="elasticsearchTemplate"
class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
<constructor-arg name="client" ref="client"/>
</bean>
<elasticsearch:repositories base-package="org.springframework.data.elasticsearch.repositories.query"/>
</beans>