1
0
mirror of synced 2026-07-05 09:40:00 +00:00

Compare commits

...

32 Commits

Author SHA1 Message Date
Spring Buildmaster 65b9f1a638 DATAES-296 - Release version 1.3.5.RELEASE. 2016-09-20 14:01:44 +00:00
Oliver Gierke b0007a74d5 DATAES-296 - Prepare 1.3.5 (Gosling SR5). 2016-09-20 15:29:22 +02:00
Oliver Gierke a6cb7dda2e DATAES-296 - Updated changelog. 2016-09-20 15:29:15 +02:00
Oliver Gierke 9ab92c9c88 DATAES-268 - Updated changelog. 2016-09-20 11:50:46 +02:00
Oliver Gierke 7e01813ec5 DATAES-250 - Updated changelog. 2016-07-28 08:51:57 +02:00
Oliver Gierke 1f7dc37e58 DATAES-251 - Updated changelog. 2016-07-28 08:51:50 +02:00
Oliver Gierke 2c5f43f12e DATAES-249 - Updated changelog. 2016-04-06 23:14:28 +02:00
Oliver Gierke 5fb4542149 DATAES-245 - Updated changelog. 2016-04-06 18:44:40 +02:00
Oliver Gierke 2bbb1d9f71 DATAES-240 - Updated changelog. 2016-03-18 13:22:42 +01:00
Oliver Gierke cb42209c1b DATAES-235 - After release cleanups. 2016-02-23 14:18:17 +01:00
Spring Buildmaster 5a6eabf756 DATAES-235 - Prepare next development iteration. 2016-02-23 04:23:45 -08:00
Spring Buildmaster 7bc9a34c8c DATAES-235 - Release version 1.3.4 (Gosling SR4). 2016-02-23 04:23:45 -08:00
Oliver Gierke 97c279966f DATAES-235 - Prepare 1.3.4 (Gosling SR4). 2016-02-23 12:56:55 +01:00
Oliver Gierke 5b2f36f826 DATAES-235 - Updated changelog. 2016-02-23 12:56:53 +01:00
Oliver Gierke 39593ba7ab DATAES-231 - Updated changelog. 2016-02-12 22:11:13 +01:00
Oliver Gierke 96177eb2fb DATAEST-235 - Fix Surefire test execution order. 2016-02-11 17:30:24 +01:00
Oliver Gierke 9155ebb1e0 DATAES-235 - Tweaked version properties for Gosling SR4. 2016-02-11 17:04:11 +01:00
Oliver Gierke 4fca7a544e DATAES-223 - After release cleanups. 2015-12-18 10:26:35 +01:00
Spring Buildmaster f4eabda897 DATAES-223 - Prepare next development iteration. 2015-12-18 00:55:31 -08:00
Spring Buildmaster 552a2dd834 DATAES-223 - Release version 1.3.2.RELEASE (Gosling SR2). 2015-12-18 00:55:31 -08:00
Oliver Gierke e7cd8dc346 DATAES-223 - Prepare 1.3.2.RELEASE (Gosling SR2). 2015-12-18 08:30:37 +01:00
Oliver Gierke 565c420834 DATAES-223 - Updated changelog. 2015-12-18 08:30:31 +01:00
Oliver Gierke b6c9a79df2 DATAES-212 - After release cleanups. 2015-11-19 12:58:42 +01:00
Spring Buildmaster b4c5ec6a23 DATAES-212 - Prepare next development iteration. 2015-11-15 05:41:19 -08:00
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 463 additions and 152 deletions
+23 -4
View File
@@ -4,13 +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.5.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.5.RELEASE</version>
<relativePath>../spring-data-build/parent/pom.xml</relativePath>
</parent> </parent>
<name>Spring Data Elasticsearch</name> <name>Spring Data Elasticsearch</name>
@@ -24,7 +23,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.5.RELEASE</springdata.commons>
</properties> </properties>
@@ -121,10 +120,30 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.6</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<useFile>false</useFile>
<includes>
<include>**/*Tests.java</include>
</includes>
<runOrder>alphabetical</runOrder>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId> <artifactId>maven-assembly-plugin</artifactId>
@@ -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;
} }
@@ -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()};
@@ -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 +
'}';
}
} }
} }
@@ -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();
+80
View File
@@ -1,6 +1,86 @@
Spring Data Elasticsearch Changelog Spring Data Elasticsearch Changelog
=================================== ===================================
Changes in version 1.3.5.RELEASE (2016-09-20)
---------------------------------------------
* DATAES-296 - Release 1.3.5 (Gosling SR5).
Changes in version 2.0.3.RELEASE (2016-09-20)
---------------------------------------------
* DATAES-281 - Can't save entity without id setter.
* DATAES-268 - Release 2.0.3 (Hopper SR3).
Changes in version 2.1.0.M1 (2016-07-27)
----------------------------------------
* DATAES-262 - Upgrade Elasticsearch to 2.3.3.
* DATAES-250 - Release 2.1 M1 (Ingalls).
Changes in version 2.0.2.RELEASE (2016-06-15)
---------------------------------------------
* DATAES-251 - Release 2.0.2 (Hopper SR2).
Changes in version 2.0.1.RELEASE (2016-04-06)
---------------------------------------------
* DATAES-249 - Release 2.0.1 (Hopper SR1).
Changes in version 2.0.0.RELEASE (2016-04-06)
---------------------------------------------
* DATAES-245 - Release 2.0 GA (Hopper).
Changes in version 2.0.0.RC1 (2016-03-18)
-----------------------------------------
* DATAES-241 - remove commons-collections dependency and use CollectionUtils from Spring Utils.
* DATAES-240 - Release 2.0 RC1 (Hopper).
* DATAES-238 - ElasticsearchTemplate.prepareUpdate() does not preserve routing parameter which is required for updating child documents.
* DATAES-237 - path-configuration fails to load configs from inside jars.
* DATAES-236 - Clear the search contexts associated with specified scroll id.
* DATAES-234 - CDI support can fail due to Set.toString() used as Map key.
* DATAES-211 - Upgrade to Elasticsearch 2.0.
* DATAES-188 - Source filtering feature Implementation.
* DATAES-124 - ElasticSearchTemplate should expose client.
Changes in version 1.3.4.RELEASE (2016-02-23)
---------------------------------------------
* DATAES-235 - Release 1.3.4 (Gosling SR4).
Changes in version 1.4.0.M1 (2016-02-12)
----------------------------------------
* DATAES-232 - Add code of conduct.
* DATAES-231 - Release 1.4 M1 (Hopper).
* DATAES-230 - Remove unnecessary type check in AbstractElasticsearchRepository.
* DATAES-224 - ElasticsearchTemplate discards newlines in mappings and settings files.
* DATAES-221 - Adapt to changes in Spring Data Commons.
* DATAES-216 - Add support to Indices Boost.
* DATAES-210 - Typo in error message.
* DATAES-209 - Handle dynamic mapping annotation at field level.
* DATAES-194 - Tests should clean up "data" directory.
* DATAES-171 - findByIdNotIn not work.
* DATAES-94 - Bump to support ES 1.2.0.
Changes in version 1.3.2.RELEASE (2015-12-18)
---------------------------------------------
* DATAES-223 - Release 1.3.2 (Gosling).
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).
+1 -1
View File
@@ -1,4 +1,4 @@
Spring Data Elasticsearch 1.3 GA Spring Data Elasticsearch 1.3.5
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").
@@ -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;
}
} }
@@ -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);
@@ -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);
}
@@ -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));
}
}
@@ -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>