1
0
mirror of synced 2026-07-07 10:40:02 +00:00

Compare commits

..

27 Commits

Author SHA1 Message Date
Oliver Gierke 6aa4adc977 DATAES-335 - Release version 2.1.2 (Ingalls SR2). 2017-04-19 10:11:29 +02:00
Oliver Gierke 2c7d8c6f61 DATAES-335 - Prepare 2.1.2 (Ingalls SR2). 2017-04-19 10:10:48 +02:00
Oliver Gierke 05c9804d16 DATAES-335 - Updated changelog. 2017-04-19 10:10:44 +02:00
Oliver Gierke c72eaa79e9 DATAES-311 - Updated changelog. 2017-04-10 14:33:12 +02:00
Oliver Gierke 399611d68a DATAES-326 - Updated changelog. 2017-03-02 16:57:55 +01:00
Oliver Gierke f79caa9626 DATAES-327 - After release cleanups. 2017-03-02 10:21:57 +01:00
Oliver Gierke b8ff15e69c DATAES-327 - Prepare next development iteration. 2017-03-02 10:21:40 +01:00
Oliver Gierke c28f41a2c4 DATAES-327 - Release version 2.1.1 (Ingalls SR1). 2017-03-02 09:41:29 +01:00
Oliver Gierke 686921c46e DATAES-327 - Prepare 2.1.1 (Ingalls SR1). 2017-03-02 09:33:29 +01:00
Oliver Gierke d1e11ef5f9 DATAES-327 - Updated changelog. 2017-03-02 09:33:11 +01:00
Mark Paluch c0ef590038 DATAES-329 - Remove references to Assert single-arg methods.
Replace references to Assert single-arg methods with references to methods accepting the test object and message.

Related ticket: SPR-15196.
2017-02-02 08:42:56 +01:00
Oliver Gierke 692142ea65 DATAES-319 - Updated changelog. 2017-01-26 12:08:53 +01:00
Oliver Gierke 6e2331b040 DATAES-320 - After release cleanups. 2017-01-26 10:57:48 +01:00
Oliver Gierke 29910fc9ef DATAES-320 - Prepare next development iteration. 2017-01-26 10:57:45 +01:00
Oliver Gierke 38604eb64d DATAES-320 - Release version 2.1 GA (Ingalls). 2017-01-26 10:27:11 +01:00
Oliver Gierke 344f439778 DATAES-320 - Prepare 2.1 GA (Ingalls). 2017-01-26 10:26:36 +01:00
Oliver Gierke ea07d697ad DATAES-320 - Updated changelog. 2017-01-26 10:26:34 +01:00
Mark Paluch 6b549339c8 DATAES-322 - Update project documentation with the CLA tool integration. 2017-01-13 11:32:01 +01:00
Oliver Gierke 3c2894e45d DATAES-304 - Updated changelog. 2016-12-21 19:35:39 +01:00
Oliver Gierke d921f9d9a3 DATAES-275 - After release cleanups. 2016-12-21 16:33:14 +01:00
Oliver Gierke af1f658712 DATAES-275 - Prepare next development iteration. 2016-12-21 16:33:11 +01:00
Oliver Gierke 18c30078ba DATAES-275 - Release version 2.1 RC1 (Ingalls). 2016-12-21 16:16:52 +01:00
Oliver Gierke 812e202f15 DATAES-275 - Prepare 2.1 RC1 (Ingalls). 2016-12-21 16:15:48 +01:00
Oliver Gierke bf4cadbdd8 DATAES-275 - Updated changelog. 2016-12-21 16:15:44 +01:00
Oliver Gierke 200f1771d5 DATAES-315 - Adapt API in ElasticsearchRepositoryFactoryBean.
Related ticket: DATACMNS-891.
2016-12-15 15:25:17 +01:00
Mark Paluch b83a097892 DATAES-313 - Register ElasticsearchRepositoryFactory in spring.factories.
This is required for the switch in support for multi-store detection.

Related ticket: DATACMNS-952.
2016-12-06 09:12:53 +01:00
Oliver Gierke 6d08e92117 DATAES-306 - Updated changelog. 2016-11-23 13:52:48 +01:00
209 changed files with 14640 additions and 16178 deletions
+21 -18
View File
@@ -1,18 +1,21 @@
atlassian-ide-plugin.xml
## Ignore svn files
.svn
## ignore any target dir
target
## Ignore project files created by Eclipse
.settings
.project
.classpath
## Ignore project files created by IntelliJ IDEA
*.iml
*.ipr
*.iws
.idea
atlassian-ide-plugin.xml
## Ignore svn files
.svn
## ignore any target dir
target
##ignore only top level data dir - local node data files for unit tests
/data
## Ignore project files created by Eclipse
.settings
.project
.classpath
## Ignore project files created by IntelliJ IDEA
*.iml
*.ipr
*.iws
.idea
+13 -11
View File
@@ -31,7 +31,7 @@ Add the Maven dependency:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>x.y.z.RELEASE</version>
<version>2.0.4.RELEASE</version>
</dependency>
```
@@ -42,7 +42,7 @@ the appropriate dependency version.
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>x.y.z.BUILD-SNAPSHOT</version>
<version>2.1.0.BUILD-SNAPSHOT</version>
</dependency>
<repository>
@@ -52,13 +52,15 @@ the appropriate dependency version.
</repository>
```
| spring data elasticsearch | elasticsearch |
|:-------------------------:|:-------------:|
| 3.1.x | 6.2.2 |
| 3.0.x | 5.5.0 |
| 2.1.x | 2.4.0 |
| 2.0.x | 2.2.0 |
| 1.3.x | 1.5.2 |
| spring data elasticsearch | elasticsearch |
|:-----------------------------------:|:-------------:|
| 2.0.4.RELEASE | 2.4.0 |
| 2.0.0.RELEASE | 2.2.0 |
| 1.4.0.M1 | 1.7.3 |
| 1.3.0.RELEASE | 1.5.2 |
| 1.2.0.RELEASE | 1.4.4 |
| 1.1.0.RELEASE | 1.3.2 |
| 1.0.0.RELEASE | 1.1.1 |
### ElasticsearchRepository
@@ -238,8 +240,8 @@ Using Transport Client
Here are some ways for you to get involved in the community:
* Get involved with the Spring community on Stack OverFlow. Please help out on the [forum](https://stackoverflow.com/questions/tagged/spring-data-elasticsearch) by responding to questions and joining the debate.
* Create [JIRA](https://jira.spring.io/browse/DATAES/) tickets for bugs and new features and comment and vote on the ones that you are interested in.
* Get involved with the Spring community on the Spring Community Forums. Please help out on the [forum](http://forum.springsource.org/forumdisplay.php?f=80) by responding to questions and joining the debate.
* Create [JIRA](https://jira.springframework.org/browse/DATAES) tickets for bugs and new features and comment and vote on the ones that you are interested in.
* Github is for social coding: if you want to write code, we encourage contributions through pull requests from [forks of this repository](http://help.github.com/forking/). If you want to contribute code this way, please reference a JIRA ticket as well covering the specific issue you are addressing.
* Watch for upcoming articles on Spring by [subscribing](http://www.springsource.org/node/feed) to springframework.org
+17 -57
View File
@@ -4,12 +4,13 @@
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>3.1.3.RELEASE</version>
<version>2.1.2.RELEASE</version>
<parent>
<groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId>
<version>2.1.3.RELEASE</version>
<version>1.9.2.RELEASE</version>
<relativePath>../spring-data-build/parent/pom.xml</relativePath>
</parent>
<name>Spring Data Elasticsearch</name>
@@ -17,12 +18,14 @@
<url>https://github.com/spring-projects/spring-data-elasticsearch</url>
<properties>
<dist.key>DATAES</dist.key>
<commonscollections>3.2.1</commonscollections>
<commonslang>2.6</commonslang>
<elasticsearch>6.2.2</elasticsearch>
<log4j>2.9.1</log4j>
<springdata.commons>2.1.3.RELEASE</springdata.commons>
<java-module-name>spring.data.elasticsearch</java-module-name>
<elasticsearch>2.4.0</elasticsearch>
<springdata.commons>1.13.2.RELEASE</springdata.commons>
</properties>
<dependencies>
@@ -56,7 +59,6 @@
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>${commonslang}</version>
<scope>test</scope>
</dependency>
<!-- JODA Time -->
@@ -68,41 +70,23 @@
<!-- Elasticsearch -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>${elasticsearch}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${slf4j}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j}</version>
<scope>test</scope>
</dependency>
<!-- Jackson JSON Mapper -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson}</version>
</dependency>
<!-- CDI -->
<dependency>
<groupId>javax.enterprise</groupId>
@@ -117,18 +101,11 @@
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.openwebbeans.test</groupId>
<artifactId>cditest-owb</artifactId>
<version>1.2.8</version>
<version>${webbeans}</version>
<scope>test</scope>
<exclusions>
<exclusion>
@@ -141,15 +118,6 @@
</exclusion>
</exclusions>
</dependency>
<!-- Upgrade xbean to 4.5 to prevent incompatibilities due to ASM versions -->
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-asm5-shaded</artifactId>
<version>4.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
@@ -157,14 +125,6 @@
<scope>test</scope>
</dependency>
<dependency>
<!-- required by elasticsearch -->
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>transport-netty4-client</artifactId>
<version>${elasticsearch}</version>
<!--<scope>test</scope>-->
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
@@ -237,12 +197,12 @@
<ciManagement>
<system>Bamboo</system>
<url>https://build.spring.io/browse/SPRINGDATAES</url>
<url>http://build.springsource.org/browse/SPRINGDATAES</url>
</ciManagement>
<issueManagement>
<system>JIRA</system>
<url>https://jira.spring.io/browse/DATAES</url>
<url>https://jira.springsource.org/browse/DATAES</url>
</issueManagement>
</project>
@@ -23,55 +23,50 @@ Page<SampleEntity> sampleEntities =
----
====
[[elasticsearch.scroll]]
== Using Scroll For Big Result Set
[[elasticsearch.scan.and.scroll]]
== Using Scan And Scroll For Big Result Set
Elasticsearch has a scroll API for getting big result set in chunks. `ElasticsearchTemplate` has startScroll and continueScroll methods that can be used as below.
Elasticsearch has scan and scroll feature for getting big result set in chunks. `ElasticsearchTemplate` has scan and scroll methods that can be used as below.
.Using startScroll and continueScroll
.Using Scan and Scroll
====
[source,java]
----
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(matchAllQuery())
.withIndices(INDEX_NAME)
.withTypes(TYPE_NAME)
.withFields("message")
.withPageable(PageRequest.of(0, 10))
.withIndices("test-index")
.withTypes("test-type")
.withPageable(new PageRequest(0,1))
.build();
Page<SampleEntity> scroll = elasticsearchTemplate.startScroll(1000, searchQuery, SampleEntity.class);
String scrollId = ((ScrolledPage) scroll).getScrollId();
List<SampleEntity> sampleEntities = new ArrayList<>();
while (scroll.hasContent()) {
sampleEntities.addAll(scroll.getContent());
scrollId = ((ScrolledPage) scroll).getScrollId();
scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class);
}
elasticsearchTemplate.clearScroll(scrollId);
String scrollId = elasticsearchTemplate.scan(searchQuery,1000,false);
List<SampleEntity> sampleEntities = new ArrayList<SampleEntity>();
boolean hasRecords = true;
while (hasRecords){
Page<SampleEntity> page = elasticsearchTemplate.scroll(scrollId, 5000L , new ResultsMapper<SampleEntity>()
{
@Override
public Page<SampleEntity> mapResults(SearchResponse response) {
List<SampleEntity> chunk = new ArrayList<SampleEntity>();
for(SearchHit searchHit : response.getHits()){
if(response.getHits().getHits().length <= 0) {
return null;
}
SampleEntity user = new SampleEntity();
user.setId(searchHit.getId());
user.setMessage((String)searchHit.getSource().get("message"));
chunk.add(user);
}
return new PageImpl<SampleEntity>(chunk);
}
});
if(page != null) {
sampleEntities.addAll(page.getContent());
hasRecords = page.hasNextPage();
}
else{
hasRecords = false;
}
}
}
----
====
`ElasticsearchTemplate` additionally has the stream method which wraps the scan and scroll operations into a CloseableIterator.
.Using stream
====
[source,java]
----
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(matchAllQuery())
.withIndices(INDEX_NAME)
.withTypes(TYPE_NAME)
.withFields("message")
.withPageable(PageRequest.of(0, 10))
.build();
CloseableIterator<SampleEntity> stream = elasticsearchTemplate.stream(searchQuery, SampleEntity.class);
List<SampleEntity> sampleEntities = new ArrayList<>();
while (stream.hasNext()) {
sampleEntities.add(stream.next());
}
----
====
@@ -1,51 +1,51 @@
/*
* Copyright 2013 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.elasticsearch;
import java.util.Map;
/**
* ElasticsearchException
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class ElasticsearchException extends RuntimeException {
private Map<String, String> failedDocuments;
public ElasticsearchException(String message) {
super(message);
}
public ElasticsearchException(String message, Throwable cause) {
super(message, cause);
}
public ElasticsearchException(String message, Throwable cause, Map<String, String> failedDocuments) {
super(message, cause);
this.failedDocuments = failedDocuments;
}
public ElasticsearchException(String message, Map<String, String> failedDocuments) {
super(message);
this.failedDocuments = failedDocuments;
}
public Map<String, String> getFailedDocuments() {
return failedDocuments;
}
}
/*
* Copyright 2013 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.elasticsearch;
import java.util.Map;
/**
* ElasticsearchException
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class ElasticsearchException extends RuntimeException {
private Map<String, String> failedDocuments;
public ElasticsearchException(String message) {
super(message);
}
public ElasticsearchException(String message, Throwable cause) {
super(message, cause);
}
public ElasticsearchException(String message, Throwable cause, Map<String, String> failedDocuments) {
super(message, cause);
this.failedDocuments = failedDocuments;
}
public ElasticsearchException(String message, Map<String, String> failedDocuments) {
super(message);
this.failedDocuments = failedDocuments;
}
public Map<String, String> getFailedDocuments() {
return failedDocuments;
}
}
@@ -32,6 +32,8 @@ public @interface CompletionField {
String analyzer() default "simple";
boolean payloads() default false;
boolean preserveSeparators() default true;
boolean preservePositionIncrements() default true;
@@ -1,51 +1,51 @@
/*
* Copyright 2013 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.elasticsearch.annotations;
import java.lang.annotation.*;
import org.springframework.data.annotation.Persistent;
/**
* Document
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Mason Chan
*/
@Persistent
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface Document {
String indexName();
String type() default "";
boolean useServerConfiguration() default false;
short shards() default 5;
short replicas() default 1;
String refreshInterval() default "1s";
String indexStoreType() default "fs";
boolean createIndex() default true;
}
/*
* Copyright 2013 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.elasticsearch.annotations;
import java.lang.annotation.*;
import org.springframework.data.annotation.Persistent;
/**
* Document
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Mason Chan
*/
@Persistent
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface Document {
String indexName();
String type() default "";
boolean useServerConfiguration() default false;
short shards() default 5;
short replicas() default 1;
String refreshInterval() default "1s";
String indexStoreType() default "fs";
boolean createIndex() default true;
}
@@ -1,62 +1,56 @@
/*
* Copyright 2013-2018 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.elasticsearch.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
* @author Jonathan Yan
* @author Jakub Vavrik
* @author Kevin Leturc
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
@Inherited
public @interface Field {
FieldType type() default FieldType.Auto;
boolean index() default true;
DateFormat format() default DateFormat.none;
String pattern() default "";
boolean store() default false;
boolean fielddata() default false;
String searchAnalyzer() default "";
String analyzer() default "";
String normalizer() default "";
String[] ignoreFields() default {};
boolean includeInParent() default false;
String[] copyTo() default {};
}
/*
* Copyright 2013 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.elasticsearch.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
* @author Jonathan Yan
* @author Jakub Vavrik
* @author Kevin Leturc
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
@Inherited
public @interface Field {
FieldType type() default FieldType.Auto;
FieldIndex index() default FieldIndex.analyzed;
DateFormat format() default DateFormat.none;
String pattern() default "";
boolean store() default false;
String searchAnalyzer() default "";
String analyzer() default "";
String[] ignoreFields() default {};
boolean includeInParent() default false;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2018 the original author or authors.
* Copyright 2014 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.
@@ -13,17 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.elasticsearch.core;
import org.springframework.data.domain.Page;
package org.springframework.data.elasticsearch.annotations;
/**
* A score-aware page gaining information about max score.
*
* @param <T>
* @author Sascha Woo
* @author Artur Konczak
* @author Mohsin Husen
* @author Alexander Volz
* @author Dennis Maaß
*/
public interface ScoredPage<T> extends Page<T> {
float getMaxScore();
public enum FieldIndex {
not_analyzed, analyzed, no
}
@@ -21,17 +21,5 @@ package org.springframework.data.elasticsearch.annotations;
* @author Artur Konczak
*/
public enum FieldType {
Text,
Integer,
Long,
Date,
Float,
Double,
Boolean,
Object,
Auto,
Nested,
Ip,
Attachment,
Keyword
String, Integer, Long, Date, Float, Double, Boolean, Object, Auto, Nested, Ip, Attachment
}
@@ -25,4 +25,8 @@ import java.lang.annotation.*;
@Documented
public @interface GeoPointField {
boolean geoHashPrefix() default false;
String geoHashPrecision() default "0";
}
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014 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.
@@ -21,9 +21,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Artur Konczak
* @author Mohsin Husen
* @author Sascha Woo
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@@ -33,19 +31,11 @@ public @interface InnerField {
FieldType type();
boolean index() default true;
DateFormat format() default DateFormat.none;
String pattern() default "";
FieldIndex index() default FieldIndex.analyzed;
boolean store() default false;
boolean fielddata() default false;
String searchAnalyzer() default "";
String analyzer() default "";
String normalizer() default "";
String indexAnalyzer() default "";
}
@@ -1,45 +1,45 @@
/*
* Copyright 2013 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.elasticsearch.annotations;
import java.lang.annotation.*;
/**
* Query
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface Query {
/**
* Elasticsearch query to be used when executing query. May contain placeholders eg. ?0
*
* @return
*/
String value() default "";
/**
* Named Query Named looked up by repository.
*
* @return
*/
String name() default "";
}
/*
* Copyright 2013 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.elasticsearch.annotations;
import java.lang.annotation.*;
/**
* Query
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface Query {
/**
* Elasticsearch query to be used when executing query. May contain placeholders eg. ?0
*
* @return
*/
String value() default "";
/**
* Named Query Named looked up by repository.
*
* @return
*/
String name() default "";
}
@@ -1,23 +0,0 @@
package org.springframework.data.elasticsearch.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.data.annotation.ReadOnlyProperty;
/**
* Specifies that this field is used for storing the document score.
*
* @author Sascha Woo
* @since 3.1
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
@Inherited
@ReadOnlyProperty
public @interface Score {}
@@ -1,102 +0,0 @@
/*
* Copyright 2018 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.elasticsearch.client;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import org.elasticsearch.common.transport.TransportAddress;
import org.springframework.data.util.Streamable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Value object to represent a list of cluster nodes.
*
* @author Oliver Gierke
* @since 3.1
*/
class ClusterNodes implements Streamable<TransportAddress> {
public static ClusterNodes DEFAULT = ClusterNodes.of("127.0.0.1:9300");
private static final String COLON = ":";
private static final String COMMA = ",";
private final List<TransportAddress> clusterNodes;
/**
* Creates a new {@link ClusterNodes} by parsing the given source.
*
* @param source must not be {@literal null} or empty.
*/
private ClusterNodes(String source) {
Assert.hasText(source, "Cluster nodes source must not be null or empty!");
String[] nodes = StringUtils.delimitedListToStringArray(source, COMMA);
this.clusterNodes = Arrays.stream(nodes).map(node -> {
String[] segments = StringUtils.delimitedListToStringArray(node, COLON);
Assert.isTrue(segments.length == 2,
() -> String.format("Invalid cluster node %s in %s! Must be in the format host:port!", node, source));
String host = segments[0].trim();
String port = segments[1].trim();
Assert.hasText(host, () -> String.format("No host name given cluster node %s!", node));
Assert.hasText(port, () -> String.format("No port given in cluster node %s!", node));
return new TransportAddress(toInetAddress(host), Integer.valueOf(port));
}).collect(Collectors.toList());
}
/**
* Creates a new {@link ClusterNodes} by parsing the given source. The expected format is a comma separated list of
* host-port-combinations separated by a colon: {@code host:port,host:port,…}.
*
* @param source must not be {@literal null} or empty.
* @return
*/
public static ClusterNodes of(String source) {
return new ClusterNodes(source);
}
/*
* (non-Javadoc)
* @see java.lang.Iterable#iterator()
*/
@Override
public Iterator<TransportAddress> iterator() {
return clusterNodes.iterator();
}
private static InetAddress toInetAddress(String host) {
try {
return InetAddress.getByName(host);
} catch (UnknownHostException o_O) {
throw new IllegalArgumentException(o_O);
}
}
}
@@ -1,144 +1,127 @@
/*
* Copyright 2015-2017 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.elasticsearch.client;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.node.InternalSettingsPreparer;
import org.elasticsearch.node.Node;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.transport.Netty4Plugin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.StringUtils;
import static java.util.Arrays.*;
/**
* NodeClientFactoryBean
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Ilkang Na
*/
public class NodeClientFactoryBean implements FactoryBean<Client>, InitializingBean, DisposableBean {
private static final Logger logger = LoggerFactory.getLogger(NodeClientFactoryBean.class);
private boolean local;
private boolean enableHttp;
private String clusterName;
private NodeClient nodeClient;
private String pathData;
private String pathHome;
private String pathConfiguration;
public static class TestNode extends Node {
public TestNode(Settings preparedSettings, Collection<Class<? extends Plugin>> classpathPlugins) {
super(InternalSettingsPreparer.prepareEnvironment(preparedSettings, null), classpathPlugins);
}
}
NodeClientFactoryBean() {
}
public NodeClientFactoryBean(boolean local) {
this.local = local;
}
@Override
public NodeClient getObject() throws Exception {
return nodeClient;
}
@Override
public Class<? extends Client> getObjectType() {
return NodeClient.class;
}
@Override
public boolean isSingleton() {
return true;
}
@Override
public void afterPropertiesSet() throws Exception {
nodeClient = (NodeClient) new TestNode(
Settings.builder().put(loadConfig())
.put("transport.type", "netty4")
.put("http.type", "netty4")
.put("path.home", this.pathHome)
.put("path.data", this.pathData)
.put("cluster.name", this.clusterName)
.put("node.max_local_storage_nodes", 100)
.build(), asList(Netty4Plugin.class)).start().client();
}
private Settings loadConfig() throws IOException {
if (!StringUtils.isEmpty(pathConfiguration)) {
InputStream stream = getClass().getClassLoader().getResourceAsStream(pathConfiguration);
if (stream != null) {
return Settings.builder().loadFromStream(pathConfiguration, getClass().getClassLoader().getResourceAsStream(pathConfiguration), false).build();
}
logger.error(String.format("Unable to read node configuration from file [%s]", pathConfiguration));
}
return Settings.builder().build();
}
public void setLocal(boolean local) {
this.local = local;
}
public void setEnableHttp(boolean enableHttp) {
this.enableHttp = enableHttp;
}
public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
public void setPathData(String pathData) {
this.pathData = pathData;
}
public void setPathHome(String pathHome) {
this.pathHome = pathHome;
}
public void setPathConfiguration(String configuration) {
this.pathConfiguration = configuration;
}
@Override
public void destroy() throws Exception {
try {
logger.info("Closing elasticSearch client");
if (nodeClient != null) {
nodeClient.close();
}
} catch (final Exception e) {
logger.error("Error closing ElasticSearch client: ", e);
}
}
}
/*
* Copyright 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.elasticsearch.client;
import static org.elasticsearch.node.NodeBuilder.*;
import java.io.InputStream;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
/**
* NodeClientFactoryBean
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class NodeClientFactoryBean implements FactoryBean<NodeClient>, InitializingBean, DisposableBean {
private static final Logger logger = LoggerFactory.getLogger(NodeClientFactoryBean.class);
private boolean local;
private boolean enableHttp;
private String clusterName;
private NodeClient nodeClient;
private String pathData;
private String pathHome;
private String pathConfiguration;
NodeClientFactoryBean() {
}
public NodeClientFactoryBean(boolean local) {
this.local = local;
}
@Override
public NodeClient getObject() throws Exception {
return nodeClient;
}
@Override
public Class<? extends Client> getObjectType() {
return NodeClient.class;
}
@Override
public boolean isSingleton() {
return true;
}
@Override
public void afterPropertiesSet() throws Exception {
nodeClient = (NodeClient) nodeBuilder().settings(Settings.builder().put(loadConfig())
.put("http.enabled", String.valueOf(this.enableHttp))
.put("path.home", this.pathHome)
.put("path.data", this.pathData))
.clusterName(this.clusterName).local(this.local).node()
.client();
}
private Settings loadConfig() {
if (StringUtils.isNotBlank(pathConfiguration)) {
InputStream stream = getClass().getClassLoader().getResourceAsStream(pathConfiguration);
if (stream != null) {
return Settings.builder().loadFromStream(pathConfiguration, getClass().getClassLoader().getResourceAsStream(pathConfiguration)).build();
}
logger.error(String.format("Unable to read node configuration from file [%s]", pathConfiguration));
}
return Settings.builder().build();
}
public void setLocal(boolean local) {
this.local = local;
}
public void setEnableHttp(boolean enableHttp) {
this.enableHttp = enableHttp;
}
public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
public void setPathData(String pathData) {
this.pathData = pathData;
}
public void setPathHome(String pathHome) {
this.pathHome = pathHome;
}
public void setPathConfiguration(String configuration) {
this.pathConfiguration = configuration;
}
@Override
public void destroy() throws Exception {
try {
logger.info("Closing elasticSearch client");
if (nodeClient != null) {
nodeClient.close();
}
} catch (final Exception e) {
logger.error("Error closing ElasticSearch client: ", e);
}
}
}
@@ -15,16 +15,20 @@
*/
package org.springframework.data.elasticsearch.client;
import static org.apache.commons.lang.StringUtils.*;
import java.net.InetAddress;
import java.util.Properties;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
/**
* TransportClientFactoryBean
@@ -33,13 +37,12 @@ import org.springframework.beans.factory.InitializingBean;
* @author Mohsin Husen
* @author Jakub Vavrik
* @author Piotr Betkier
* @author Ilkang Na
* @author Oliver Gierke
*/
public class TransportClientFactoryBean implements FactoryBean<TransportClient>, InitializingBean, DisposableBean {
private static final Logger logger = LoggerFactory.getLogger(TransportClientFactoryBean.class);
private ClusterNodes clusterNodes = ClusterNodes.of("127.0.0.1:9300");
private String clusterNodes = "127.0.0.1:9300";
private String clusterName = "elasticsearch";
private Boolean clientTransportSniff = true;
private Boolean clientIgnoreClusterName = Boolean.FALSE;
@@ -47,6 +50,8 @@ public class TransportClientFactoryBean implements FactoryBean<TransportClient>,
private String clientNodesSamplerInterval = "5s";
private TransportClient client;
private Properties properties;
static final String COLON = ":";
static final String COMMA = ",";
@Override
public void destroy() throws Exception {
@@ -81,25 +86,22 @@ public class TransportClientFactoryBean implements FactoryBean<TransportClient>,
}
protected void buildClient() throws Exception {
client = new PreBuiltTransportClient(settings());
clusterNodes.stream() //
.peek(it -> logger.info("Adding transport node : " + it.toString())) //
.forEach(client::addTransportAddress);
client = TransportClient.builder().settings(settings()).build();
Assert.hasText(clusterNodes, "[Assertion failed] clusterNodes settings missing.");
for (String clusterNode : split(clusterNodes, COMMA)) {
String hostName = substringBeforeLast(clusterNode, COLON);
String port = substringAfterLast(clusterNode, COLON);
Assert.hasText(hostName, "[Assertion failed] missing host name in 'clusterNodes'");
Assert.hasText(port, "[Assertion failed] missing port in 'clusterNodes'");
logger.info("adding transport node : " + clusterNode);
client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(hostName), Integer.valueOf(port)));
}
client.connectedNodes();
}
private Settings settings() {
if (properties != null) {
Settings.Builder builder = Settings.builder();
properties.forEach((key, value) -> {
builder.put(key.toString(), value.toString());
});
return builder.build();
return Settings.builder().put(properties).build();
}
return Settings.builder()
.put("cluster.name", clusterName)
@@ -111,7 +113,7 @@ public class TransportClientFactoryBean implements FactoryBean<TransportClient>,
}
public void setClusterNodes(String clusterNodes) {
this.clusterNodes = ClusterNodes.of(clusterNodes);
this.clusterNodes = clusterNodes;
}
public void setClusterName(String clusterName) {
@@ -1,41 +1,41 @@
/*
* Copyright 2013 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.elasticsearch.config;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
import org.springframework.data.elasticsearch.repository.config.ElasticsearchRepositoryConfigExtension;
import org.springframework.data.repository.config.RepositoryBeanDefinitionParser;
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
/**
* ElasticsearchNamespaceHandler
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class ElasticsearchNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
RepositoryConfigurationExtension extension = new ElasticsearchRepositoryConfigExtension();
RepositoryBeanDefinitionParser parser = new RepositoryBeanDefinitionParser(extension);
registerBeanDefinitionParser("repositories", parser);
registerBeanDefinitionParser("node-client", new NodeClientBeanDefinitionParser());
registerBeanDefinitionParser("transport-client", new TransportClientBeanDefinitionParser());
}
}
/*
* Copyright 2013 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.elasticsearch.config;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
import org.springframework.data.elasticsearch.repository.config.ElasticsearchRepositoryConfigExtension;
import org.springframework.data.repository.config.RepositoryBeanDefinitionParser;
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
/**
* ElasticsearchNamespaceHandler
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class ElasticsearchNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
RepositoryConfigurationExtension extension = new ElasticsearchRepositoryConfigExtension();
RepositoryBeanDefinitionParser parser = new RepositoryBeanDefinitionParser(extension);
registerBeanDefinitionParser("repositories", parser);
registerBeanDefinitionParser("node-client", new NodeClientBeanDefinitionParser());
registerBeanDefinitionParser("transport-client", new TransportClientBeanDefinitionParser());
}
}
@@ -1,57 +1,57 @@
/*
* Copyright 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.elasticsearch.config;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.elasticsearch.client.NodeClientFactoryBean;
import org.w3c.dom.Element;
/**
* NodeClientBeanDefinitionParser
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class NodeClientBeanDefinitionParser extends AbstractBeanDefinitionParser {
@Override
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(NodeClientFactoryBean.class);
setLocalSettings(element, builder);
return getSourcedBeanDefinition(builder, element, parserContext);
}
private void setLocalSettings(Element element, BeanDefinitionBuilder builder) {
builder.addPropertyValue("local", Boolean.valueOf(element.getAttribute("local")));
builder.addPropertyValue("clusterName", element.getAttribute("cluster-name"));
builder.addPropertyValue("enableHttp", Boolean.valueOf(element.getAttribute("http-enabled")));
builder.addPropertyValue("pathData", element.getAttribute("path-data"));
builder.addPropertyValue("pathHome", element.getAttribute("path-home"));
builder.addPropertyValue("pathConfiguration", element.getAttribute("path-configuration"));
}
private AbstractBeanDefinition getSourcedBeanDefinition(BeanDefinitionBuilder builder, Element source,
ParserContext context) {
AbstractBeanDefinition definition = builder.getBeanDefinition();
definition.setSource(context.extractSource(source));
return definition;
}
}
/*
* Copyright 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.elasticsearch.config;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.elasticsearch.client.NodeClientFactoryBean;
import org.w3c.dom.Element;
/**
* NodeClientBeanDefinitionParser
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class NodeClientBeanDefinitionParser extends AbstractBeanDefinitionParser {
@Override
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(NodeClientFactoryBean.class);
setLocalSettings(element, builder);
return getSourcedBeanDefinition(builder, element, parserContext);
}
private void setLocalSettings(Element element, BeanDefinitionBuilder builder) {
builder.addPropertyValue("local", Boolean.valueOf(element.getAttribute("local")));
builder.addPropertyValue("clusterName", element.getAttribute("cluster-name"));
builder.addPropertyValue("enableHttp", Boolean.valueOf(element.getAttribute("http-enabled")));
builder.addPropertyValue("pathData", element.getAttribute("path-data"));
builder.addPropertyValue("pathHome", element.getAttribute("path-home"));
builder.addPropertyValue("pathConfiguration", element.getAttribute("path-configuration"));
}
private AbstractBeanDefinition getSourcedBeanDefinition(BeanDefinitionBuilder builder, Element source,
ParserContext context) {
AbstractBeanDefinition definition = builder.getBeanDefinition();
definition.setSource(context.extractSource(source));
return definition;
}
}
@@ -1,56 +1,56 @@
/*
* Copyright 2013 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.elasticsearch.config;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.elasticsearch.client.TransportClientFactoryBean;
import org.w3c.dom.Element;
/**
* TransportClientBeanDefinitionParser
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class TransportClientBeanDefinitionParser extends AbstractBeanDefinitionParser {
@Override
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(TransportClientFactoryBean.class);
setConfigurations(element, builder);
return getSourcedBeanDefinition(builder, element, parserContext);
}
private void setConfigurations(Element element, BeanDefinitionBuilder builder) {
builder.addPropertyValue("clusterNodes", element.getAttribute("cluster-nodes"));
builder.addPropertyValue("clusterName", element.getAttribute("cluster-name"));
builder.addPropertyValue("clientTransportSniff", Boolean.valueOf(element.getAttribute("client-transport-sniff")));
builder.addPropertyValue("clientIgnoreClusterName", Boolean.valueOf(element.getAttribute("client-transport-ignore-cluster-name")));
builder.addPropertyValue("clientPingTimeout", element.getAttribute("client-transport-ping-timeout"));
builder.addPropertyValue("clientNodesSamplerInterval", element.getAttribute("client-transport-nodes-sampler-interval"));
}
private AbstractBeanDefinition getSourcedBeanDefinition(BeanDefinitionBuilder builder, Element source,
ParserContext context) {
AbstractBeanDefinition definition = builder.getBeanDefinition();
definition.setSource(context.extractSource(source));
return definition;
}
}
/*
* Copyright 2013 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.elasticsearch.config;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.elasticsearch.client.TransportClientFactoryBean;
import org.w3c.dom.Element;
/**
* TransportClientBeanDefinitionParser
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class TransportClientBeanDefinitionParser extends AbstractBeanDefinitionParser {
@Override
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(TransportClientFactoryBean.class);
setConfigurations(element, builder);
return getSourcedBeanDefinition(builder, element, parserContext);
}
private void setConfigurations(Element element, BeanDefinitionBuilder builder) {
builder.addPropertyValue("clusterNodes", element.getAttribute("cluster-nodes"));
builder.addPropertyValue("clusterName", element.getAttribute("cluster-name"));
builder.addPropertyValue("clientTransportSniff", Boolean.valueOf(element.getAttribute("client-transport-sniff")));
builder.addPropertyValue("clientIgnoreClusterName", Boolean.valueOf(element.getAttribute("client-transport-ignore-cluster-name")));
builder.addPropertyValue("clientPingTimeout", element.getAttribute("client-transport-ping-timeout"));
builder.addPropertyValue("clientNodesSamplerInterval", element.getAttribute("client-transport-nodes-sampler-interval"));
}
private AbstractBeanDefinition getSourcedBeanDefinition(BeanDefinitionBuilder builder, Element source,
ParserContext context) {
AbstractBeanDefinition definition = builder.getBeanDefinition();
definition.setSource(context.extractSource(source));
return definition;
}
}
@@ -15,11 +15,11 @@
*/
package org.springframework.data.elasticsearch.core;
import static org.apache.commons.lang.StringUtils.*;
import java.io.IOException;
import org.springframework.data.elasticsearch.ElasticsearchException;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* @author Artur Konczak
@@ -29,14 +29,11 @@ public abstract class AbstractResultMapper implements ResultsMapper {
private EntityMapper entityMapper;
public AbstractResultMapper(EntityMapper entityMapper) {
Assert.notNull(entityMapper, "EntityMapper must not be null!");
this.entityMapper = entityMapper;
}
public <T> T mapEntity(String source, Class<T> clazz) {
if (StringUtils.isEmpty(source)) {
if (isBlank(source)) {
return null;
}
try {
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2017 the original author or authors.
* Copyright 2013-2016 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.
@@ -45,7 +45,7 @@ class CriteriaFilterProcessor {
QueryBuilder createFilterFromCriteria(Criteria criteria) {
List<QueryBuilder> fbList = new LinkedList<>();
List<QueryBuilder> fbList = new LinkedList<QueryBuilder>();
QueryBuilder filter = null;
ListIterator<Criteria> chainIterator = criteria.getCriteriaChain().listIterator();
@@ -86,7 +86,7 @@ class CriteriaFilterProcessor {
private List<QueryBuilder> createFilterFragmentForCriteria(Criteria chainedCriteria) {
Iterator<Criteria.CriteriaEntry> it = chainedCriteria.getFilterCriteriaEntries().iterator();
List<QueryBuilder> filterList = new LinkedList<>();
List<QueryBuilder> filterList = new LinkedList<QueryBuilder>();
String fieldName = chainedCriteria.getField().getName();
Assert.notNull(fieldName, "Unknown field");
@@ -116,8 +116,8 @@ class CriteriaFilterProcessor {
Object[] valArray = (Object[]) value;
Assert.noNullElements(valArray, "Geo distance filter takes 2 not null elements array as parameter.");
Assert.isTrue(valArray.length == 2, "Geo distance filter takes a 2-elements array as parameter.");
Assert.isTrue(valArray[0] instanceof GeoPoint || valArray[0] instanceof String || valArray[0] instanceof Point, "First element of a geo distance filter must be a GeoPoint, a Point or a text");
Assert.isTrue(valArray[1] instanceof String || valArray[1] instanceof Distance, "Second element of a geo distance filter must be a text or a Distance");
Assert.isTrue(valArray[0] instanceof GeoPoint || valArray[0] instanceof String || valArray[0] instanceof Point, "First element of a geo distance filter must be a GeoPoint, a Point or a String");
Assert.isTrue(valArray[1] instanceof String || valArray[1] instanceof Distance, "Second element of a geo distance filter must be a String or a Distance");
StringBuilder dist = new StringBuilder();
@@ -129,15 +129,15 @@ class CriteriaFilterProcessor {
if (valArray[0] instanceof GeoPoint) {
GeoPoint loc = (GeoPoint) valArray[0];
geoDistanceQueryBuilder.point(loc.getLat(),loc.getLon()).distance(dist.toString()).geoDistance(GeoDistance.PLANE);
geoDistanceQueryBuilder.lat(loc.getLat()).lon(loc.getLon()).distance(dist.toString()).geoDistance(GeoDistance.PLANE);
} else if (valArray[0] instanceof Point) {
GeoPoint loc = GeoPoint.fromPoint((Point) valArray[0]);
geoDistanceQueryBuilder.point(loc.getLat(), loc.getLon()).distance(dist.toString()).geoDistance(GeoDistance.PLANE);
geoDistanceQueryBuilder.lat(loc.getLat()).lon(loc.getLon()).distance(dist.toString()).geoDistance(GeoDistance.PLANE);
} else {
String loc = (String) valArray[0];
if (loc.contains(",")) {
String c[] = loc.split(",");
geoDistanceQueryBuilder.point(Double.parseDouble(c[0]), Double.parseDouble(c[1])).distance(dist.toString()).geoDistance(GeoDistance.PLANE);
geoDistanceQueryBuilder.lat(Double.parseDouble(c[0])).lon(Double.parseDouble(c[1])).distance(dist.toString()).geoDistance(GeoDistance.PLANE);
} else {
geoDistanceQueryBuilder.geohash(loc).distance(dist.toString()).geoDistance(GeoDistance.PLANE);
}
@@ -159,7 +159,7 @@ class CriteriaFilterProcessor {
oneParameterBBox((GeoBoundingBoxQueryBuilder) filter, valArray[0]);
} else if (valArray.length == 2) {
//2x GeoPoint
//2x text
//2x String
twoParameterBBox((GeoBoundingBoxQueryBuilder) filter, valArray);
} else {
//error
@@ -206,7 +206,8 @@ class CriteriaFilterProcessor {
geoBBox = (GeoBox) value;
}
filter.setCorners(geoBBox.getTopLeft().getLat(), geoBBox.getTopLeft().getLon(), geoBBox.getBottomRight().getLat(), geoBBox.getBottomRight().getLon());
filter.topLeft(geoBBox.getTopLeft().getLat(), geoBBox.getTopLeft().getLon());
filter.bottomRight(geoBBox.getBottomRight().getLat(), geoBBox.getBottomRight().getLon());
}
private static boolean isType(Object[] array, Class clazz) {
@@ -219,20 +220,22 @@ class CriteriaFilterProcessor {
}
private void twoParameterBBox(GeoBoundingBoxQueryBuilder filter, Object[] values) {
Assert.isTrue(isType(values, GeoPoint.class) || isType(values, String.class), " both elements of boundedBy filter must be type of GeoPoint or text(format lat,lon or geohash)");
Assert.isTrue(isType(values, GeoPoint.class) || isType(values, String.class), " both elements of boundedBy filter must be type of GeoPoint or String(format lat,lon or geohash)");
if (values[0] instanceof GeoPoint) {
GeoPoint topLeft = (GeoPoint) values[0];
GeoPoint bottomRight = (GeoPoint) values[1];
filter.setCorners(topLeft.getLat(), topLeft.getLon(), bottomRight.getLat(), bottomRight.getLon());
filter.topLeft(topLeft.getLat(), topLeft.getLon());
filter.bottomRight(bottomRight.getLat(), bottomRight.getLon());
} else {
String topLeft = (String) values[0];
String bottomRight = (String) values[1];
filter.setCorners(topLeft, bottomRight);
filter.topLeft(topLeft);
filter.bottomRight(bottomRight);
}
}
private List<QueryBuilder> buildNegationFilter(String fieldName, Iterator<Criteria.CriteriaEntry> it) {
List<QueryBuilder> notFilterList = new LinkedList<>();
List<QueryBuilder> notFilterList = new LinkedList<QueryBuilder>();
while (it.hasNext()) {
Criteria.CriteriaEntry criteriaEntry = it.next();
@@ -1,206 +1,210 @@
/*
* Copyright 2013-2017 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.elasticsearch.core;
import static org.elasticsearch.index.query.Operator.AND;
import static org.elasticsearch.index.query.QueryBuilders.*;
import static org.springframework.data.elasticsearch.core.query.Criteria.*;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import org.apache.lucene.queryparser.flexible.core.util.StringUtils;
import org.elasticsearch.index.query.*;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.util.Assert;
/**
* CriteriaQueryProcessor
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Franck Marchand
* @author Artur Konczak
*/
class CriteriaQueryProcessor {
QueryBuilder createQueryFromCriteria(Criteria criteria) {
if (criteria == null)
return null;
List<QueryBuilder> shouldQueryBuilderList = new LinkedList<>();
List<QueryBuilder> mustNotQueryBuilderList = new LinkedList<>();
List<QueryBuilder> mustQueryBuilderList = new LinkedList<>();
ListIterator<Criteria> chainIterator = criteria.getCriteriaChain().listIterator();
QueryBuilder firstQuery = null;
boolean negateFirstQuery = false;
while (chainIterator.hasNext()) {
Criteria chainedCriteria = chainIterator.next();
QueryBuilder queryFragmentForCriteria = createQueryFragmentForCriteria(chainedCriteria);
if (queryFragmentForCriteria != null) {
if (firstQuery == null) {
firstQuery = queryFragmentForCriteria;
negateFirstQuery = chainedCriteria.isNegating();
continue;
}
if (chainedCriteria.isOr()) {
shouldQueryBuilderList.add(queryFragmentForCriteria);
} else if (chainedCriteria.isNegating()) {
mustNotQueryBuilderList.add(queryFragmentForCriteria);
} else {
mustQueryBuilderList.add(queryFragmentForCriteria);
}
}
}
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;
if (!shouldQueryBuilderList.isEmpty() || !mustNotQueryBuilderList.isEmpty() || !mustQueryBuilderList.isEmpty()) {
query = boolQuery();
for (QueryBuilder qb : shouldQueryBuilderList) {
query.should(qb);
}
for (QueryBuilder qb : mustNotQueryBuilderList) {
query.mustNot(qb);
}
for (QueryBuilder qb : mustQueryBuilderList) {
query.must(qb);
}
}
return query;
}
private QueryBuilder createQueryFragmentForCriteria(Criteria chainedCriteria) {
if (chainedCriteria.getQueryCriteriaEntries().isEmpty())
return null;
Iterator<Criteria.CriteriaEntry> it = chainedCriteria.getQueryCriteriaEntries().iterator();
boolean singeEntryCriteria = (chainedCriteria.getQueryCriteriaEntries().size() == 1);
String fieldName = chainedCriteria.getField().getName();
Assert.notNull(fieldName, "Unknown field");
QueryBuilder query = null;
if (singeEntryCriteria) {
Criteria.CriteriaEntry entry = it.next();
query = processCriteriaEntry(entry, fieldName);
} else {
query = boolQuery();
while (it.hasNext()) {
Criteria.CriteriaEntry entry = it.next();
((BoolQueryBuilder) query).must(processCriteriaEntry(entry, fieldName));
}
}
addBoost(query, chainedCriteria.getBoost());
return query;
}
private QueryBuilder processCriteriaEntry(Criteria.CriteriaEntry entry,/* OperationKey key, Object value,*/ String fieldName) {
Object value = entry.getValue();
if (value == null) {
return null;
}
OperationKey key = entry.getKey();
QueryBuilder query = null;
String searchText = StringUtils.toString(value);
Iterable<Object> collection = null;
switch (key) {
case EQUALS:
query = queryStringQuery(searchText).field(fieldName).defaultOperator(AND);
break;
case CONTAINS:
query = queryStringQuery("*" + searchText + "*").field(fieldName).analyzeWildcard(true);
break;
case STARTS_WITH:
query = queryStringQuery(searchText + "*").field(fieldName).analyzeWildcard(true);
break;
case ENDS_WITH:
query = queryStringQuery("*" + searchText).field(fieldName).analyzeWildcard(true);
break;
case EXPRESSION:
query = queryStringQuery(searchText).field(fieldName);
break;
case LESS_EQUAL:
query = rangeQuery(fieldName).lte(value);
break;
case GREATER_EQUAL:
query = rangeQuery(fieldName).gte(value);
break;
case BETWEEN:
Object[] ranges = (Object[]) value;
query = rangeQuery(fieldName).from(ranges[0]).to(ranges[1]);
break;
case LESS:
query = rangeQuery(fieldName).lt(value);
break;
case GREATER:
query = rangeQuery(fieldName).gt(value);
break;
case FUZZY:
query = fuzzyQuery(fieldName, searchText);
break;
case IN:
query = boolQuery();
collection = (Iterable<Object>) value;
for (Object item : collection) {
((BoolQueryBuilder) query).should(queryStringQuery(item.toString()).field(fieldName));
}
break;
case NOT_IN:
query = boolQuery();
collection = (Iterable<Object>) value;
for (Object item : collection) {
((BoolQueryBuilder) query).mustNot(queryStringQuery(item.toString()).field(fieldName));
}
break;
}
return query;
}
private void addBoost(QueryBuilder query, float boost) {
if (Float.isNaN(boost)) {
return;
}
query.boost(boost);
}
}
/*
* Copyright 2013 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.elasticsearch.core;
import static org.elasticsearch.index.query.QueryBuilders.*;
import static org.springframework.data.elasticsearch.core.query.Criteria.*;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import org.apache.lucene.queryparser.flexible.core.util.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
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.util.Assert;
/**
* CriteriaQueryProcessor
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Franck Marchand
* @author Artur Konczak
*/
class CriteriaQueryProcessor {
QueryBuilder createQueryFromCriteria(Criteria criteria) {
if (criteria == null)
return null;
List<QueryBuilder> shouldQueryBuilderList = new LinkedList<QueryBuilder>();
List<QueryBuilder> mustNotQueryBuilderList = new LinkedList<QueryBuilder>();
List<QueryBuilder> mustQueryBuilderList = new LinkedList<QueryBuilder>();
ListIterator<Criteria> chainIterator = criteria.getCriteriaChain().listIterator();
QueryBuilder firstQuery = null;
boolean negateFirstQuery = false;
while (chainIterator.hasNext()) {
Criteria chainedCriteria = chainIterator.next();
QueryBuilder queryFragmentForCriteria = createQueryFragmentForCriteria(chainedCriteria);
if (queryFragmentForCriteria != null) {
if (firstQuery == null) {
firstQuery = queryFragmentForCriteria;
negateFirstQuery = chainedCriteria.isNegating();
continue;
}
if (chainedCriteria.isOr()) {
shouldQueryBuilderList.add(queryFragmentForCriteria);
} else if (chainedCriteria.isNegating()) {
mustNotQueryBuilderList.add(queryFragmentForCriteria);
} else {
mustQueryBuilderList.add(queryFragmentForCriteria);
}
}
}
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;
if (!shouldQueryBuilderList.isEmpty() || !mustNotQueryBuilderList.isEmpty() || !mustQueryBuilderList.isEmpty()) {
query = boolQuery();
for (QueryBuilder qb : shouldQueryBuilderList) {
query.should(qb);
}
for (QueryBuilder qb : mustNotQueryBuilderList) {
query.mustNot(qb);
}
for (QueryBuilder qb : mustQueryBuilderList) {
query.must(qb);
}
}
return query;
}
private QueryBuilder createQueryFragmentForCriteria(Criteria chainedCriteria) {
if (chainedCriteria.getQueryCriteriaEntries().isEmpty())
return null;
Iterator<Criteria.CriteriaEntry> it = chainedCriteria.getQueryCriteriaEntries().iterator();
boolean singeEntryCriteria = (chainedCriteria.getQueryCriteriaEntries().size() == 1);
String fieldName = chainedCriteria.getField().getName();
Assert.notNull(fieldName, "Unknown field");
QueryBuilder query = null;
if (singeEntryCriteria) {
Criteria.CriteriaEntry entry = it.next();
query = processCriteriaEntry(entry, fieldName);
} else {
query = boolQuery();
while (it.hasNext()) {
Criteria.CriteriaEntry entry = it.next();
((BoolQueryBuilder) query).must(processCriteriaEntry(entry, fieldName));
}
}
addBoost(query, chainedCriteria.getBoost());
return query;
}
private QueryBuilder processCriteriaEntry(Criteria.CriteriaEntry entry,/* OperationKey key, Object value,*/ String fieldName) {
Object value = entry.getValue();
if (value == null) {
return null;
}
OperationKey key = entry.getKey();
QueryBuilder query = null;
String searchText = StringUtils.toString(value);
Iterable<Object> collection = null;
switch (key) {
case EQUALS:
query = queryStringQuery(searchText).field(fieldName).defaultOperator(QueryStringQueryBuilder.Operator.AND);
break;
case CONTAINS:
query = queryStringQuery("*" + searchText + "*").field(fieldName).analyzeWildcard(true);
break;
case STARTS_WITH:
query = queryStringQuery(searchText + "*").field(fieldName).analyzeWildcard(true);
break;
case ENDS_WITH:
query = queryStringQuery("*" + searchText).field(fieldName).analyzeWildcard(true);
break;
case EXPRESSION:
query = queryStringQuery(searchText).field(fieldName);
break;
case LESS_EQUAL:
query = rangeQuery(fieldName).lte(value);
break;
case GREATER_EQUAL:
query = rangeQuery(fieldName).gte(value);
break;
case BETWEEN:
Object[] ranges = (Object[]) value;
query = rangeQuery(fieldName).from(ranges[0]).to(ranges[1]);
break;
case LESS:
query = rangeQuery(fieldName).lt(value);
break;
case GREATER:
query = rangeQuery(fieldName).gt(value);
break;
case FUZZY:
query = fuzzyQuery(fieldName, searchText);
break;
case IN:
query = boolQuery();
collection = (Iterable<Object>) value;
for (Object item : collection) {
((BoolQueryBuilder) query).should(queryStringQuery(item.toString()).field(fieldName));
}
break;
case NOT_IN:
query = boolQuery();
collection = (Iterable<Object>) value;
for (Object item : collection) {
((BoolQueryBuilder) query).mustNot(queryStringQuery(item.toString()).field(fieldName));
}
break;
}
return query;
}
private void addBoost(QueryBuilder query, float boost) {
if (Float.isNaN(boost)) {
return;
}
if (query instanceof BoostableQueryBuilder) {
((BoostableQueryBuilder) query).boost(boost);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014 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.
@@ -16,142 +16,52 @@
package org.springframework.data.elasticsearch.core;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.springframework.data.annotation.ReadOnlyProperty;
import org.springframework.data.elasticsearch.core.geo.CustomGeoModule;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.util.Assert;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.core.geo.CustomGeoModule;
import org.springframework.data.geo.*;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.module.SimpleModule;
/**
* EntityMapper based on a Jackson {@link ObjectMapper}.
* DocumentMapper using jackson
*
* @author Artur Konczak
* @author Petar Tahchiev
* @author Oliver Gierke
*/
public class DefaultEntityMapper implements EntityMapper {
private ObjectMapper objectMapper;
/**
* Creates a new {@link DefaultEntityMapper} using the given {@link MappingContext}.
*
* @param context must not be {@literal null}.
*/
public DefaultEntityMapper(
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> context) {
Assert.notNull(context, "MappingContext must not be null!");
public DefaultEntityMapper() {
objectMapper = new ObjectMapper();
objectMapper.registerModule(new SpringDataElasticsearchModule(context));
objectMapper.registerModule(new CustomGeoModule());
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
objectMapper.registerModule(new CustomGeoModule());
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.core.EntityMapper#mapToString(java.lang.Object)
*/
@Override
public String mapToString(Object object) throws IOException {
return objectMapper.writeValueAsString(object);
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.core.EntityMapper#mapToObject(java.lang.String, java.lang.Class)
*/
@Override
public <T> T mapToObject(String source, Class<T> clazz) throws IOException {
return objectMapper.readValue(source, clazz);
}
/**
* A simple Jackson module to register the {@link SpringDataSerializerModifier}.
*
* @author Oliver Gierke
* @since 3.1
*/
private static class SpringDataElasticsearchModule extends SimpleModule {
private static final long serialVersionUID = -9168968092458058966L;
/**
* Creates a new {@link SpringDataElasticsearchModule} using the given {@link MappingContext}.
*
* @param context must not be {@literal null}.
*/
public SpringDataElasticsearchModule(
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> context) {
Assert.notNull(context, "MappingContext must not be null!");
setSerializerModifier(new SpringDataSerializerModifier(context));
}
/**
* A {@link BeanSerializerModifier} that will drop properties annotated with {@link ReadOnlyProperty} for
* serialization.
*
* @author Oliver Gierke
* @since 3.1
*/
private static class SpringDataSerializerModifier extends BeanSerializerModifier {
private final MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> context;
public SpringDataSerializerModifier(
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> context) {
Assert.notNull(context, "MappingContext must not be null!");
this.context = context;
}
/*
* (non-Javadoc)
* @see com.fasterxml.jackson.databind.ser.BeanSerializerModifier#changeProperties(com.fasterxml.jackson.databind.SerializationConfig, com.fasterxml.jackson.databind.BeanDescription, java.util.List)
*/
@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription description,
List<BeanPropertyWriter> properties) {
Class<?> type = description.getBeanClass();
ElasticsearchPersistentEntity<?> entity = context.getPersistentEntity(type);
if (entity == null) {
return super.changeProperties(config, description, properties);
}
List<BeanPropertyWriter> result = new ArrayList<>(properties.size());
for (BeanPropertyWriter beanPropertyWriter : properties) {
ElasticsearchPersistentProperty property = entity.getPersistentProperty(beanPropertyWriter.getName());
if (property != null && property.isWritable()) {
result.add(beanPropertyWriter);
}
}
return result;
}
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2016 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.
@@ -15,6 +15,7 @@
*/
package org.springframework.data.elasticsearch.core;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
@@ -23,12 +24,16 @@ import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.MultiGetItemResponse;
import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.document.DocumentField;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHitField;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.ElasticsearchException;
import org.springframework.data.elasticsearch.annotations.Document;
@@ -37,84 +42,58 @@ import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.util.Assert;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import org.springframework.util.StringUtils;
/**
* @author Artur Konczak
* @author Petar Tahchiev
* @author Young Gu
* @author Oliver Gierke
* @author Chris White
* @author Mark Paluch
* @author Ilkang Na
* @author Sascha Woo
*/
public class DefaultResultMapper extends AbstractResultMapper {
private final MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext;
private MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext;
public DefaultResultMapper() {
this(new SimpleElasticsearchMappingContext());
super(new DefaultEntityMapper());
}
public DefaultResultMapper(MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext) {
super(new DefaultEntityMapper(mappingContext));
Assert.notNull(mappingContext, "MappingContext must not be null!");
super(new DefaultEntityMapper());
this.mappingContext = mappingContext;
}
public DefaultResultMapper(EntityMapper entityMapper) {
this(new SimpleElasticsearchMappingContext(), entityMapper);
super(entityMapper);
}
public DefaultResultMapper(
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext,
EntityMapper entityMapper) {
super(entityMapper);
Assert.notNull(mappingContext, "MappingContext must not be null!");
this.mappingContext = mappingContext;
}
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
long totalHits = response.getHits().getTotalHits();
float maxScore = response.getHits().getMaxScore();
List<T> results = new ArrayList<>();
long totalHits = response.getHits().totalHits();
List<T> results = new ArrayList<T>();
for (SearchHit hit : response.getHits()) {
if (hit != null) {
T result = null;
if (!StringUtils.isEmpty(hit.getSourceAsString())) {
result = mapEntity(hit.getSourceAsString(), clazz);
if (StringUtils.isNotBlank(hit.sourceAsString())) {
result = mapEntity(hit.sourceAsString(), clazz);
} else {
result = mapEntity(hit.getFields().values(), clazz);
}
setPersistentEntityId(result, hit.getId(), clazz);
setPersistentEntityVersion(result, hit.getVersion(), clazz);
setPersistentEntityScore(result, hit.getScore(), clazz);
populateScriptFields(result, hit);
results.add(result);
}
}
return new AggregatedPageImpl<T>(results, pageable, totalHits, response.getAggregations(), response.getScrollId(),
maxScore);
return new AggregatedPageImpl<T>(results, pageable, totalHits, response.getAggregations());
}
private <T> void populateScriptFields(T result, SearchHit hit) {
@@ -123,14 +102,14 @@ public class DefaultResultMapper extends AbstractResultMapper {
ScriptedField scriptedField = field.getAnnotation(ScriptedField.class);
if (scriptedField != null) {
String name = scriptedField.name().isEmpty() ? field.getName() : scriptedField.name();
DocumentField searchHitField = hit.getFields().get(name);
SearchHitField searchHitField = hit.getFields().get(name);
if (searchHitField != null) {
field.setAccessible(true);
try {
field.set(result, searchHitField.getValue());
} catch (IllegalArgumentException e) {
throw new ElasticsearchException(
"failed to set scripted field: " + name + " with value: " + searchHitField.getValue(), e);
throw new ElasticsearchException("failed to set scripted field: " + name + " with value: "
+ searchHitField.getValue(), e);
} catch (IllegalAccessException e) {
throw new ElasticsearchException("failed to access scripted field: " + name, e);
}
@@ -140,17 +119,18 @@ public class DefaultResultMapper extends AbstractResultMapper {
}
}
private <T> T mapEntity(Collection<DocumentField> values, Class<T> clazz) {
private <T> T mapEntity(Collection<SearchHitField> values, Class<T> clazz) {
return mapEntity(buildJSONFromFields(values), clazz);
}
private String buildJSONFromFields(Collection<DocumentField> values) {
private String buildJSONFromFields(Collection<SearchHitField> values) {
JsonFactory nodeFactory = new JsonFactory();
try {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
JsonGenerator generator = nodeFactory.createGenerator(stream, JsonEncoding.UTF8);
generator.writeStartObject();
for (DocumentField value : values) {
for (SearchHitField value : values) {
if (value.getValues().size() > 1) {
generator.writeArrayFieldStart(value.getName());
for (Object val : value.getValues()) {
@@ -174,19 +154,17 @@ public class DefaultResultMapper extends AbstractResultMapper {
T result = mapEntity(response.getSourceAsString(), clazz);
if (result != null) {
setPersistentEntityId(result, response.getId(), clazz);
setPersistentEntityVersion(result, response.getVersion(), clazz);
}
return result;
}
@Override
public <T> LinkedList<T> mapResults(MultiGetResponse responses, Class<T> clazz) {
LinkedList<T> list = new LinkedList<>();
LinkedList<T> list = new LinkedList<T>();
for (MultiGetItemResponse response : responses.getResponses()) {
if (!response.isFailed() && response.getResponse().isExists()) {
T result = mapEntity(response.getResponse().getSourceAsString(), clazz);
setPersistentEntityId(result, response.getResponse().getId(), clazz);
setPersistentEntityVersion(result, response.getResponse().getVersion(), clazz);
list.add(result);
}
}
@@ -194,48 +172,16 @@ public class DefaultResultMapper extends AbstractResultMapper {
}
private <T> void setPersistentEntityId(T result, String id, Class<T> clazz) {
if (clazz.isAnnotationPresent(Document.class)) {
ElasticsearchPersistentEntity<?> persistentEntity = mappingContext.getRequiredPersistentEntity(clazz);
ElasticsearchPersistentProperty idProperty = persistentEntity.getIdProperty();
if (mappingContext != null && clazz.isAnnotationPresent(Document.class)) {
ElasticsearchPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(clazz);
PersistentProperty<?> idProperty = persistentEntity.getIdProperty();
// Only deal with String because ES generated Ids are strings !
if (idProperty != null && idProperty.getType().isAssignableFrom(String.class)) {
persistentEntity.getPropertyAccessor(result).setProperty(idProperty, id);
}
}
}
private <T> void setPersistentEntityVersion(T result, long version, Class<T> clazz) {
if (clazz.isAnnotationPresent(Document.class)) {
ElasticsearchPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(clazz);
ElasticsearchPersistentProperty versionProperty = persistentEntity.getVersionProperty();
// Only deal with Long because ES versions are longs !
if (versionProperty != null && versionProperty.getType().isAssignableFrom(Long.class)) {
// check that a version was actually returned in the response, -1 would indicate that
// a search didn't request the version ids in the response, which would be an issue
Assert.isTrue(version != -1, "Version in response is -1");
persistentEntity.getPropertyAccessor(result).setProperty(versionProperty, version);
}
}
}
private <T> void setPersistentEntityScore(T result, float score, Class<T> clazz) {
if (clazz.isAnnotationPresent(Document.class)) {
ElasticsearchPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(clazz);
if (!entity.hasScoreProperty()) {
return;
}
entity.getPropertyAccessor(result) //
.setProperty(entity.getScoreProperty(), score);
}
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014 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.
@@ -19,8 +19,8 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
import org.elasticsearch.search.aggregations.bucket.range.Range;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
@@ -33,14 +33,7 @@ import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
import org.springframework.data.elasticsearch.core.facet.FacetResult;
import org.springframework.data.elasticsearch.core.facet.request.RangeFacetRequest;
import org.springframework.data.elasticsearch.core.facet.result.HistogramResult;
import org.springframework.data.elasticsearch.core.facet.result.IntervalUnit;
import org.springframework.data.elasticsearch.core.facet.result.RangeResult;
import org.springframework.data.elasticsearch.core.facet.result.StatisticalResult;
import org.springframework.data.elasticsearch.core.facet.result.Term;
import org.springframework.data.elasticsearch.core.facet.result.TermResult;
import static java.util.Optional.ofNullable;
import org.springframework.data.elasticsearch.core.facet.result.*;
/**
* Container for query result and facet results
@@ -49,21 +42,19 @@ import static java.util.Optional.ofNullable;
* @author Mohsin Husen
* @author Artur Konczak
* @author Jonathan Yan
* @author Philipp Kräutli
* @author Remco Zigterman
*/
@Deprecated
public abstract class FacetedPageImpl<T> extends PageImpl<T> implements FacetedPage<T>, AggregatedPage<T> {
private List<FacetResult> facets;
private Map<String, FacetResult> mapOfFacets = new HashMap<>();
private Map<String, FacetResult> mapOfFacets = new HashMap<String, FacetResult>();
public FacetedPageImpl(List<T> content) {
super(content);
}
public FacetedPageImpl(List<T> content, Pageable pageable, long total) {
super(content, ofNullable(pageable).orElse(Pageable.unpaged()), total);
super(content, pageable, total);
}
@Override
@@ -93,76 +84,47 @@ public abstract class FacetedPageImpl<T> extends PageImpl<T> implements FacetedP
* Lazy conversion from aggregation to old facets
*/
private void processAggregations() {
if (facets != null) {
return;
}
facets = new ArrayList<>();
Aggregations aggregations = getAggregations();
if (aggregations == null) {
return;
}
for (Aggregation agg : aggregations) {
processAggregation(agg);
}
}
private void processAggregation(Aggregation agg)
{
if (agg instanceof Terms) {
processTermAggregation((Terms) agg);
}
if (agg instanceof Range) {
processRangeAggregation((Range) agg);
}
if (agg instanceof ExtendedStats) {
processExtendedStatsAggregation((ExtendedStats) agg);
}
if (agg instanceof Histogram) {
processHistogramAggregation((Histogram) agg);
}
}
private void processTermAggregation(Terms agg)
{
List<Term> terms = new ArrayList<>();
for (Terms.Bucket t : agg.getBuckets()) {
terms.add(new Term(t.getKeyAsString(), t.getDocCount()));
}
addFacet(new TermResult(agg.getName(), terms, terms.size(), agg.getSumOfOtherDocCounts(), 0));
}
private void processRangeAggregation(Range agg)
{
List<? extends Range.Bucket> buckets = ((Range) agg).getBuckets();
List<org.springframework.data.elasticsearch.core.facet.result.Range> ranges = new ArrayList<>();
for (Range.Bucket b : buckets) {
ExtendedStats rStats = b.getAggregations().get(AbstractFacetRequest.INTERNAL_STATS);
if (rStats != null) {
Sum sum = b.getAggregations().get(RangeFacetRequest.RANGE_INTERNAL_SUM);
ranges.add(new org.springframework.data.elasticsearch.core.facet.result.Range((Double) b.getFrom(), (Double) b.getTo(), b.getDocCount(), sum != null ? sum.getValue() : rStats.getSum(), rStats.getCount(), rStats.getMin(), rStats.getMax()));
} else {
ranges.add(new org.springframework.data.elasticsearch.core.facet.result.Range((Double) b.getFrom(), (Double) b.getTo(), b.getDocCount(), 0, 0, 0, 0));
if (facets == null) {
facets = new ArrayList<FacetResult>();
for (Aggregation agg : getAggregations()) {
if (agg instanceof Terms) {
List<Term> terms = new ArrayList<Term>();
for (Terms.Bucket t : ((Terms) agg).getBuckets()) {
terms.add(new Term(t.getKeyAsString(), t.getDocCount()));
}
addFacet(new TermResult(agg.getName(), terms, terms.size(), ((Terms) agg).getSumOfOtherDocCounts(), 0));
}
if (agg instanceof Range) {
List<? extends Range.Bucket> buckets = ((Range) agg).getBuckets();
List<org.springframework.data.elasticsearch.core.facet.result.Range> ranges = new ArrayList<org.springframework.data.elasticsearch.core.facet.result.Range>();
for (Range.Bucket b : buckets) {
ExtendedStats rStats = (ExtendedStats) b.getAggregations().get(AbstractFacetRequest.INTERNAL_STATS);
if (rStats != null) {
Sum sum = (Sum) b.getAggregations().get(RangeFacetRequest.RANGE_INTERNAL_SUM);
ranges.add(new org.springframework.data.elasticsearch.core.facet.result.Range((Double) b.getFrom(), (Double) b.getTo(), b.getDocCount(), sum != null ? sum.getValue() : rStats.getSum(), rStats.getCount(), rStats.getMin(), rStats.getMax()));
} else {
ranges.add(new org.springframework.data.elasticsearch.core.facet.result.Range((Double) b.getFrom(), (Double) b.getTo(), b.getDocCount(), 0, 0, 0, 0));
}
}
addFacet(new RangeResult(agg.getName(), ranges));
}
if (agg instanceof ExtendedStats) {
ExtendedStats stats = (ExtendedStats) agg;
addFacet(new StatisticalResult(agg.getName(), stats.getCount(), stats.getMax(), stats.getMin(), stats.getAvg(), stats.getStdDeviation(), stats.getSumOfSquares(), stats.getSum(), stats.getVariance()));
}
if (agg instanceof Histogram) {
List<IntervalUnit> intervals = new ArrayList<IntervalUnit>();
for (Histogram.Bucket h : ((Histogram) agg).getBuckets()) {
ExtendedStats hStats = (ExtendedStats) h.getAggregations().get(AbstractFacetRequest.INTERNAL_STATS);
if (hStats != null) {
intervals.add(new IntervalUnit(((DateTime) h.getKey()).getMillis(), h.getDocCount(), h.getDocCount(), hStats.getSum(), hStats.getAvg(), hStats.getMin(), hStats.getMax()));
} else {
intervals.add(new IntervalUnit(((DateTime) h.getKey()).getMillis(), h.getDocCount(), h.getDocCount(), 0, 0, 0, 0));
}
}
addFacet(new HistogramResult(agg.getName(), intervals));
}
}
}
addFacet(new RangeResult(agg.getName(), ranges));
}
private void processExtendedStatsAggregation(ExtendedStats agg)
{
addFacet(new StatisticalResult(agg.getName(), agg.getCount(), agg.getMax(), agg.getMin(), agg.getAvg(), agg.getStdDeviation(), agg.getSumOfSquares(), agg.getSum(), agg.getVariance()));
}
private void processHistogramAggregation(Histogram agg)
{
List<IntervalUnit> intervals = new ArrayList<>();
for (Histogram.Bucket h : agg.getBuckets()) {
ExtendedStats hStats = h.getAggregations().get(AbstractFacetRequest.INTERNAL_STATS);
if (hStats != null) {
intervals.add(new IntervalUnit(((DateTime) h.getKey()).getMillis(), h.getDocCount(), h.getDocCount(), hStats.getSum(), hStats.getAvg(), hStats.getMin(), hStats.getMax()));
} else {
intervals.add(new IntervalUnit(((DateTime) h.getKey()).getMillis(), h.getDocCount(), h.getDocCount(), 0, 0, 0, 0));
}
}
addFacet(new HistogramResult(agg.getName(), intervals));
}
}
@@ -1,395 +1,361 @@
/*
* Copyright 2014-2017 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.elasticsearch.core;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.springframework.core.ResolvableType;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.annotation.Transient;
import org.springframework.data.elasticsearch.annotations.CompletionField;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import org.springframework.data.elasticsearch.annotations.GeoPointField;
import org.springframework.data.elasticsearch.annotations.InnerField;
import org.springframework.data.elasticsearch.annotations.Mapping;
import org.springframework.data.elasticsearch.annotations.MultiField;
import org.springframework.data.elasticsearch.core.completion.Completion;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.StringUtils;
import static org.elasticsearch.common.xcontent.XContentFactory.*;
import static org.springframework.util.StringUtils.*;
/**
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
* @author Kevin Leturc
* @author Alexander Volz
* @author Dennis Maaß
* @author Pavel Luhin
* @author Mark Paluch
* @author Sascha Woo
* @author Nordine Bittich
*/
class MappingBuilder {
public static final String FIELD_DATA = "fielddata";
public static final String FIELD_STORE = "store";
public static final String FIELD_TYPE = "type";
public static final String FIELD_INDEX = "index";
public static final String FIELD_FORMAT = "format";
public static final String FIELD_SEARCH_ANALYZER = "search_analyzer";
public static final String FIELD_INDEX_ANALYZER = "analyzer";
public static final String FIELD_NORMALIZER = "normalizer";
public static final String FIELD_PROPERTIES = "properties";
public static final String FIELD_PARENT = "_parent";
public static final String FIELD_COPY_TO = "copy_to";
public static final String COMPLETION_PRESERVE_SEPARATORS = "preserve_separators";
public static final String COMPLETION_PRESERVE_POSITION_INCREMENTS = "preserve_position_increments";
public static final String COMPLETION_MAX_INPUT_LENGTH = "max_input_length";
public static final String TYPE_VALUE_KEYWORD = "keyword";
public static final String TYPE_VALUE_GEO_POINT = "geo_point";
public static final String TYPE_VALUE_COMPLETION = "completion";
public static final String TYPE_VALUE_GEO_HASH_PREFIX = "geohash_prefix";
public static final String TYPE_VALUE_GEO_HASH_PRECISION = "geohash_precision";
private static SimpleTypeHolder SIMPLE_TYPE_HOLDER = SimpleTypeHolder.DEFAULT;
static XContentBuilder buildMapping(Class clazz, String indexType, String idFieldName, String parentType) throws IOException {
XContentBuilder mapping = jsonBuilder().startObject().startObject(indexType);
// Parent
if (hasText(parentType)) {
mapping.startObject(FIELD_PARENT).field(FIELD_TYPE, parentType).endObject();
}
// Properties
XContentBuilder xContentBuilder = mapping.startObject(FIELD_PROPERTIES);
mapEntity(xContentBuilder, clazz, true, idFieldName, "", false, FieldType.Auto, null);
return xContentBuilder.endObject().endObject().endObject();
}
private static void mapEntity(XContentBuilder xContentBuilder, Class clazz, boolean isRootObject, String idFieldName,
String nestedObjectFieldName, boolean nestedOrObjectField, FieldType fieldType, Field fieldAnnotation) throws IOException {
java.lang.reflect.Field[] fields = retrieveFields(clazz);
if (!isRootObject && (isAnyPropertyAnnotatedAsField(fields) || nestedOrObjectField)) {
String type = FieldType.Object.toString().toLowerCase();
if (nestedOrObjectField) {
type = fieldType.toString().toLowerCase();
}
XContentBuilder t = xContentBuilder.startObject(nestedObjectFieldName).field(FIELD_TYPE, type);
if (nestedOrObjectField && FieldType.Nested == fieldType && fieldAnnotation.includeInParent()) {
t.field("include_in_parent", fieldAnnotation.includeInParent());
}
t.startObject(FIELD_PROPERTIES);
}
for (java.lang.reflect.Field field : fields) {
if (field.isAnnotationPresent(Transient.class) || isInIgnoreFields(field, fieldAnnotation)) {
continue;
}
if (field.isAnnotationPresent(Mapping.class)) {
String mappingPath = field.getAnnotation(Mapping.class).mappingPath();
if (!StringUtils.isEmpty(mappingPath)) {
ClassPathResource mappings = new ClassPathResource(mappingPath);
if (mappings.exists()) {
xContentBuilder.rawField(field.getName(), mappings.getInputStream());
continue;
}
}
}
boolean isGeoPointField = isGeoPointField(field);
boolean isCompletionField = isCompletionField(field);
Field singleField = field.getAnnotation(Field.class);
if (!isGeoPointField && !isCompletionField && isEntity(field) && isAnnotated(field)) {
if (singleField == null) {
continue;
}
boolean nestedOrObject = isNestedOrObjectField(field);
mapEntity(xContentBuilder, getFieldType(field), false, "", field.getName(), nestedOrObject, singleField.type(), field.getAnnotation(Field.class));
if (nestedOrObject) {
continue;
}
}
MultiField multiField = field.getAnnotation(MultiField.class);
if (isGeoPointField) {
applyGeoPointFieldMapping(xContentBuilder, field);
}
if (isCompletionField) {
CompletionField completionField = field.getAnnotation(CompletionField.class);
applyCompletionFieldMapping(xContentBuilder, field, completionField);
}
if (isRootObject && singleField != null && isIdField(field, idFieldName)) {
applyDefaultIdFieldMapping(xContentBuilder, field);
} else if (multiField != null) {
addMultiFieldMapping(xContentBuilder, field, multiField, isNestedOrObjectField(field));
} else if (singleField != null) {
addSingleFieldMapping(xContentBuilder, field, singleField, isNestedOrObjectField(field));
}
}
if (!isRootObject && isAnyPropertyAnnotatedAsField(fields) || nestedOrObjectField) {
xContentBuilder.endObject().endObject();
}
}
private static java.lang.reflect.Field[] retrieveFields(Class clazz) {
// Create list of fields.
List<java.lang.reflect.Field> fields = new ArrayList<>();
// Keep backing up the inheritance hierarchy.
Class targetClass = clazz;
do {
fields.addAll(Arrays.asList(targetClass.getDeclaredFields()));
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return fields.toArray(new java.lang.reflect.Field[fields.size()]);
}
private static boolean isAnnotated(java.lang.reflect.Field field) {
return field.getAnnotation(Field.class) != null ||
field.getAnnotation(MultiField.class) != null ||
field.getAnnotation(GeoPointField.class) != null ||
field.getAnnotation(CompletionField.class) != null;
}
private static void applyGeoPointFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field) throws IOException {
xContentBuilder.startObject(field.getName());
xContentBuilder.field(FIELD_TYPE, TYPE_VALUE_GEO_POINT);
xContentBuilder.endObject();
}
private static void applyCompletionFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field, CompletionField annotation) throws IOException {
xContentBuilder.startObject(field.getName());
xContentBuilder.field(FIELD_TYPE, TYPE_VALUE_COMPLETION);
if (annotation != null) {
xContentBuilder.field(COMPLETION_MAX_INPUT_LENGTH, annotation.maxInputLength());
xContentBuilder.field(COMPLETION_PRESERVE_POSITION_INCREMENTS, annotation.preservePositionIncrements());
xContentBuilder.field(COMPLETION_PRESERVE_SEPARATORS, annotation.preserveSeparators());
if (!StringUtils.isEmpty(annotation.searchAnalyzer())) {
xContentBuilder.field(FIELD_SEARCH_ANALYZER, annotation.searchAnalyzer());
}
if (!StringUtils.isEmpty(annotation.analyzer())) {
xContentBuilder.field(FIELD_INDEX_ANALYZER, annotation.analyzer());
}
}
xContentBuilder.endObject();
}
private static void applyDefaultIdFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field)
throws IOException {
xContentBuilder.startObject(field.getName())
.field(FIELD_TYPE, TYPE_VALUE_KEYWORD)
.field(FIELD_INDEX, true);
xContentBuilder.endObject();
}
/**
* Add mapping for @Field annotation
*
* @throws IOException
*/
private static void addSingleFieldMapping(XContentBuilder builder, java.lang.reflect.Field field, Field annotation, boolean nestedOrObjectField) throws IOException {
builder.startObject(field.getName());
addFieldMappingParameters(builder, annotation, nestedOrObjectField);
builder.endObject();
}
/**
* Add mapping for @MultiField annotation
*
* @throws IOException
*/
private static void addMultiFieldMapping(
XContentBuilder builder,
java.lang.reflect.Field field,
MultiField annotation,
boolean nestedOrObjectField) throws IOException {
// main field
builder.startObject(field.getName());
addFieldMappingParameters(builder, annotation.mainField(), nestedOrObjectField);
// inner fields
builder.startObject("fields");
for (InnerField innerField : annotation.otherFields()) {
builder.startObject(innerField.suffix());
addFieldMappingParameters(builder, innerField, false);
builder.endObject();
}
builder.endObject();
builder.endObject();
}
private static void addFieldMappingParameters(XContentBuilder builder, Object annotation, boolean nestedOrObjectField) throws IOException {
boolean index = true;
boolean store = false;
boolean fielddata = false;
FieldType type = null;
DateFormat dateFormat = null;
String datePattern = null;
String analyzer = null;
String searchAnalyzer = null;
String normalizer = null;
String[] copyTo = null;
if (annotation instanceof Field) {
// @Field
Field fieldAnnotation = (Field) annotation;
index = fieldAnnotation.index();
store = fieldAnnotation.store();
fielddata = fieldAnnotation.fielddata();
type = fieldAnnotation.type();
dateFormat = fieldAnnotation.format();
datePattern = fieldAnnotation.pattern();
analyzer = fieldAnnotation.analyzer();
searchAnalyzer = fieldAnnotation.searchAnalyzer();
normalizer = fieldAnnotation.normalizer();
copyTo = fieldAnnotation.copyTo();
} else if (annotation instanceof InnerField) {
// @InnerField
InnerField fieldAnnotation = (InnerField) annotation;
index = fieldAnnotation.index();
store = fieldAnnotation.store();
fielddata = fieldAnnotation.fielddata();
type = fieldAnnotation.type();
dateFormat = fieldAnnotation.format();
datePattern = fieldAnnotation.pattern();
analyzer = fieldAnnotation.analyzer();
searchAnalyzer = fieldAnnotation.searchAnalyzer();
normalizer = fieldAnnotation.normalizer();
} else {
throw new IllegalArgumentException("annotation must be an instance of @Field or @InnerField");
}
if (!nestedOrObjectField) {
builder.field(FIELD_STORE, store);
}
if (fielddata) {
builder.field(FIELD_DATA, fielddata);
}
if (type != FieldType.Auto) {
builder.field(FIELD_TYPE, type.name().toLowerCase());
if (type == FieldType.Date && dateFormat != DateFormat.none) {
builder.field(FIELD_FORMAT, dateFormat == DateFormat.custom ? datePattern : dateFormat.toString());
}
}
if (!index) {
builder.field(FIELD_INDEX, index);
}
if (!StringUtils.isEmpty(analyzer)) {
builder.field(FIELD_INDEX_ANALYZER, analyzer);
}
if (!StringUtils.isEmpty(searchAnalyzer)) {
builder.field(FIELD_SEARCH_ANALYZER, searchAnalyzer);
}
if (!StringUtils.isEmpty(normalizer)) {
builder.field(FIELD_NORMALIZER, normalizer);
}
if (copyTo != null && copyTo.length > 0) {
builder.field(FIELD_COPY_TO, copyTo);
}
}
protected static boolean isEntity(java.lang.reflect.Field field) {
TypeInformation typeInformation = ClassTypeInformation.from(field.getType());
Class<?> clazz = getFieldType(field);
boolean isComplexType = !SIMPLE_TYPE_HOLDER.isSimpleType(clazz);
return isComplexType && !Map.class.isAssignableFrom(typeInformation.getType());
}
protected static Class<?> getFieldType(java.lang.reflect.Field field) {
ResolvableType resolvableType = ResolvableType.forField(field);
if (resolvableType.isArray()) {
return resolvableType.getComponentType().getRawClass();
}
ResolvableType componentType = resolvableType.getGeneric(0);
if (Iterable.class.isAssignableFrom(field.getType())
&& componentType != ResolvableType.NONE) {
return componentType.getRawClass();
}
return resolvableType.getRawClass();
}
private static boolean isAnyPropertyAnnotatedAsField(java.lang.reflect.Field[] fields) {
if (fields != null) {
for (java.lang.reflect.Field field : fields) {
if (field.isAnnotationPresent(Field.class)) {
return true;
}
}
}
return false;
}
private static boolean isIdField(java.lang.reflect.Field field, String idFieldName) {
return idFieldName.equals(field.getName());
}
private static boolean isInIgnoreFields(java.lang.reflect.Field field, Field parentFieldAnnotation) {
if (null != parentFieldAnnotation) {
String[] ignoreFields = parentFieldAnnotation.ignoreFields();
return Arrays.asList(ignoreFields).contains(field.getName());
}
return false;
}
private static boolean isNestedOrObjectField(java.lang.reflect.Field field) {
Field fieldAnnotation = field.getAnnotation(Field.class);
return fieldAnnotation != null && (FieldType.Nested == fieldAnnotation.type() || FieldType.Object == fieldAnnotation.type());
}
private static boolean isGeoPointField(java.lang.reflect.Field field) {
return field.getType() == GeoPoint.class || field.getAnnotation(GeoPointField.class) != null;
}
private static boolean isCompletionField(java.lang.reflect.Field field) {
return field.getType() == Completion.class;
}
}
/*
* Copyright 2014-2016 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.elasticsearch.core;
import static org.apache.commons.lang.StringUtils.*;
import static org.elasticsearch.common.xcontent.XContentFactory.*;
import static org.springframework.util.StringUtils.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.springframework.core.GenericCollectionTypeResolver;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.annotation.Transient;
import org.springframework.data.elasticsearch.annotations.*;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.core.completion.Completion;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
/**
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
* @author Kevin Leturc
* @author Alexander Volz
* @author Dennis Maaß
* @author Pavel Luhin
*/
class MappingBuilder {
public static final String FIELD_STORE = "store";
public static final String FIELD_TYPE = "type";
public static final String FIELD_INDEX = "index";
public static final String FIELD_FORMAT = "format";
public static final String FIELD_SEARCH_ANALYZER = "search_analyzer";
public static final String FIELD_INDEX_ANALYZER = "analyzer";
public static final String FIELD_PROPERTIES = "properties";
public static final String FIELD_PARENT = "_parent";
public static final String COMPLETION_PAYLOADS = "payloads";
public static final String COMPLETION_PRESERVE_SEPARATORS = "preserve_separators";
public static final String COMPLETION_PRESERVE_POSITION_INCREMENTS = "preserve_position_increments";
public static final String COMPLETION_MAX_INPUT_LENGTH = "max_input_length";
public static final String INDEX_VALUE_NOT_ANALYZED = "not_analyzed";
public static final String TYPE_VALUE_STRING = "string";
public static final String TYPE_VALUE_GEO_POINT = "geo_point";
public static final String TYPE_VALUE_COMPLETION = "completion";
public static final String TYPE_VALUE_GEO_HASH_PREFIX = "geohash_prefix";
public static final String TYPE_VALUE_GEO_HASH_PRECISION = "geohash_precision";
private static SimpleTypeHolder SIMPLE_TYPE_HOLDER = new SimpleTypeHolder();
static XContentBuilder buildMapping(Class clazz, String indexType, String idFieldName, String parentType) throws IOException {
XContentBuilder mapping = jsonBuilder().startObject().startObject(indexType);
// Parent
if (hasText(parentType)) {
mapping.startObject(FIELD_PARENT).field(FIELD_TYPE, parentType).endObject();
}
// Properties
XContentBuilder xContentBuilder = mapping.startObject(FIELD_PROPERTIES);
mapEntity(xContentBuilder, clazz, true, idFieldName, EMPTY, false, FieldType.Auto, null);
return xContentBuilder.endObject().endObject().endObject();
}
private static void mapEntity(XContentBuilder xContentBuilder, Class clazz, boolean isRootObject, String idFieldName,
String nestedObjectFieldName, boolean nestedOrObjectField, FieldType fieldType, Field fieldAnnotation) throws IOException {
java.lang.reflect.Field[] fields = retrieveFields(clazz);
if (!isRootObject && (isAnyPropertyAnnotatedAsField(fields) || nestedOrObjectField)) {
String type = FieldType.Object.toString().toLowerCase();
if (nestedOrObjectField) {
type = fieldType.toString().toLowerCase();
}
XContentBuilder t = xContentBuilder.startObject(nestedObjectFieldName).field(FIELD_TYPE, type);
if (nestedOrObjectField && FieldType.Nested == fieldType && fieldAnnotation.includeInParent()) {
t.field("include_in_parent", fieldAnnotation.includeInParent());
}
t.startObject(FIELD_PROPERTIES);
}
for (java.lang.reflect.Field field : fields) {
if (field.isAnnotationPresent(Transient.class) || isInIgnoreFields(field, fieldAnnotation)) {
continue;
}
if (field.isAnnotationPresent(Mapping.class)) {
String mappingPath = field.getAnnotation(Mapping.class).mappingPath();
if (isNotBlank(mappingPath)) {
ClassPathResource mappings = new ClassPathResource(mappingPath);
if (mappings.exists()) {
xContentBuilder.rawField(field.getName(), mappings.getInputStream());
continue;
}
}
}
boolean isGeoPointField = isGeoPointField(field);
boolean isCompletionField = isCompletionField(field);
Field singleField = field.getAnnotation(Field.class);
if (!isGeoPointField && !isCompletionField && isEntity(field) && isAnnotated(field)) {
if (singleField == null) {
continue;
}
boolean nestedOrObject = isNestedOrObjectField(field);
mapEntity(xContentBuilder, getFieldType(field), false, EMPTY, field.getName(), nestedOrObject, singleField.type(), field.getAnnotation(Field.class));
if (nestedOrObject) {
continue;
}
}
MultiField multiField = field.getAnnotation(MultiField.class);
if (isGeoPointField) {
applyGeoPointFieldMapping(xContentBuilder, field);
}
if (isCompletionField) {
CompletionField completionField = field.getAnnotation(CompletionField.class);
applyCompletionFieldMapping(xContentBuilder, field, completionField);
}
if (isRootObject && singleField != null && isIdField(field, idFieldName)) {
applyDefaultIdFieldMapping(xContentBuilder, field);
} else if (multiField != null) {
addMultiFieldMapping(xContentBuilder, field, multiField, isNestedOrObjectField(field));
} else if (singleField != null) {
addSingleFieldMapping(xContentBuilder, field, singleField, isNestedOrObjectField(field));
}
}
if (!isRootObject && isAnyPropertyAnnotatedAsField(fields) || nestedOrObjectField) {
xContentBuilder.endObject().endObject();
}
}
private static java.lang.reflect.Field[] retrieveFields(Class clazz) {
// Create list of fields.
List<java.lang.reflect.Field> fields = new ArrayList<java.lang.reflect.Field>();
// Keep backing up the inheritance hierarchy.
Class targetClass = clazz;
do {
fields.addAll(Arrays.asList(targetClass.getDeclaredFields()));
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return fields.toArray(new java.lang.reflect.Field[fields.size()]);
}
private static boolean isAnnotated(java.lang.reflect.Field field) {
return field.getAnnotation(Field.class) != null ||
field.getAnnotation(MultiField.class) != null ||
field.getAnnotation(GeoPointField.class) != null ||
field.getAnnotation(CompletionField.class) != null;
}
private static void applyGeoPointFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field) throws IOException {
xContentBuilder.startObject(field.getName());
xContentBuilder.field(FIELD_TYPE, TYPE_VALUE_GEO_POINT);
GeoPointField annotation = field.getAnnotation(GeoPointField.class);
if (annotation != null) {
if (annotation.geoHashPrefix()) {
xContentBuilder.field(TYPE_VALUE_GEO_HASH_PREFIX, true);
if (StringUtils.isNotEmpty(annotation.geoHashPrecision())) {
if (NumberUtils.isNumber(annotation.geoHashPrecision())) {
xContentBuilder.field(TYPE_VALUE_GEO_HASH_PRECISION, Integer.parseInt(annotation.geoHashPrecision()));
} else {
xContentBuilder.field(TYPE_VALUE_GEO_HASH_PRECISION, annotation.geoHashPrecision());
}
}
}
}
xContentBuilder.endObject();
}
private static void applyCompletionFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field, CompletionField annotation) throws IOException {
xContentBuilder.startObject(field.getName());
xContentBuilder.field(FIELD_TYPE, TYPE_VALUE_COMPLETION);
if (annotation != null) {
xContentBuilder.field(COMPLETION_MAX_INPUT_LENGTH, annotation.maxInputLength());
xContentBuilder.field(COMPLETION_PAYLOADS, annotation.payloads());
xContentBuilder.field(COMPLETION_PRESERVE_POSITION_INCREMENTS, annotation.preservePositionIncrements());
xContentBuilder.field(COMPLETION_PRESERVE_SEPARATORS, annotation.preserveSeparators());
if (isNotBlank(annotation.searchAnalyzer())) {
xContentBuilder.field(FIELD_SEARCH_ANALYZER, annotation.searchAnalyzer());
}
if (isNotBlank(annotation.analyzer())) {
xContentBuilder.field(FIELD_INDEX_ANALYZER, annotation.analyzer());
}
}
xContentBuilder.endObject();
}
private static void applyDefaultIdFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field)
throws IOException {
xContentBuilder.startObject(field.getName())
.field(FIELD_TYPE, TYPE_VALUE_STRING)
.field(FIELD_INDEX, INDEX_VALUE_NOT_ANALYZED);
xContentBuilder.endObject();
}
/**
* Apply mapping for a single @Field annotation
*
* @throws IOException
*/
private static void addSingleFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field,
Field fieldAnnotation, boolean nestedOrObjectField) throws IOException {
xContentBuilder.startObject(field.getName());
if(!nestedOrObjectField) {
xContentBuilder.field(FIELD_STORE, fieldAnnotation.store());
}
if (FieldType.Auto != fieldAnnotation.type()) {
xContentBuilder.field(FIELD_TYPE, fieldAnnotation.type().name().toLowerCase());
if (FieldType.Date == fieldAnnotation.type() && DateFormat.none != fieldAnnotation.format()) {
xContentBuilder.field(FIELD_FORMAT, DateFormat.custom == fieldAnnotation.format()
? fieldAnnotation.pattern() : fieldAnnotation.format());
}
}
if (FieldIndex.not_analyzed == fieldAnnotation.index() || FieldIndex.no == fieldAnnotation.index()) {
xContentBuilder.field(FIELD_INDEX, fieldAnnotation.index().name().toLowerCase());
}
if (isNotBlank(fieldAnnotation.searchAnalyzer())) {
xContentBuilder.field(FIELD_SEARCH_ANALYZER, fieldAnnotation.searchAnalyzer());
}
if (isNotBlank(fieldAnnotation.analyzer())) {
xContentBuilder.field(FIELD_INDEX_ANALYZER, fieldAnnotation.analyzer());
}
xContentBuilder.endObject();
}
/**
* Apply mapping for a single nested @Field annotation
*
* @throws IOException
*/
private static void addNestedFieldMapping(XContentBuilder builder, java.lang.reflect.Field field,
InnerField annotation) throws IOException {
builder.startObject(annotation.suffix());
//builder.field(FIELD_STORE, annotation.store());
if (FieldType.Auto != annotation.type()) {
builder.field(FIELD_TYPE, annotation.type().name().toLowerCase());
}
if (FieldIndex.not_analyzed == annotation.index()) {
builder.field(FIELD_INDEX, annotation.index().name().toLowerCase());
}
if (isNotBlank(annotation.searchAnalyzer())) {
builder.field(FIELD_SEARCH_ANALYZER, annotation.searchAnalyzer());
}
if (isNotBlank(annotation.indexAnalyzer())) {
builder.field(FIELD_INDEX_ANALYZER, annotation.indexAnalyzer());
}
builder.endObject();
}
/**
* Multi field mappings for string type fields, support for sorts and facets
*
* @throws IOException
*/
private static void addMultiFieldMapping(XContentBuilder builder, java.lang.reflect.Field field,
MultiField annotation, boolean nestedOrObjectField) throws IOException {
builder.startObject(field.getName());
builder.field(FIELD_TYPE, "multi_field");
builder.startObject("fields");
//add standard field
addSingleFieldMapping(builder, field, annotation.mainField(),nestedOrObjectField);
for (InnerField innerField : annotation.otherFields()) {
addNestedFieldMapping(builder, field, innerField);
}
builder.endObject();
builder.endObject();
}
protected static boolean isEntity(java.lang.reflect.Field field) {
TypeInformation typeInformation = ClassTypeInformation.from(field.getType());
Class<?> clazz = getFieldType(field);
boolean isComplexType = !SIMPLE_TYPE_HOLDER.isSimpleType(clazz);
return isComplexType && !Map.class.isAssignableFrom(typeInformation.getType());
}
protected static Class<?> getFieldType(java.lang.reflect.Field field) {
Class<?> clazz = field.getType();
TypeInformation typeInformation = ClassTypeInformation.from(clazz);
if (typeInformation.isCollectionLike()) {
clazz = GenericCollectionTypeResolver.getCollectionFieldType(field) != null ? GenericCollectionTypeResolver.getCollectionFieldType(field) : typeInformation.getComponentType().getType();
}
return clazz;
}
private static boolean isAnyPropertyAnnotatedAsField(java.lang.reflect.Field[] fields) {
if (fields != null) {
for (java.lang.reflect.Field field : fields) {
if (field.isAnnotationPresent(Field.class)) {
return true;
}
}
}
return false;
}
private static boolean isIdField(java.lang.reflect.Field field, String idFieldName) {
return idFieldName.equals(field.getName());
}
private static boolean isInIgnoreFields(java.lang.reflect.Field field, Field parentFieldAnnotation) {
if (null != parentFieldAnnotation) {
String[] ignoreFields = parentFieldAnnotation.ignoreFields();
return Arrays.asList(ignoreFields).contains(field.getName());
}
return false;
}
private static boolean isNestedOrObjectField(java.lang.reflect.Field field) {
Field fieldAnnotation = field.getAnnotation(Field.class);
return fieldAnnotation != null && (FieldType.Nested == fieldAnnotation.type() || FieldType.Object == fieldAnnotation.type());
}
private static boolean isGeoPointField(java.lang.reflect.Field field) {
return field.getType() == GeoPoint.class || field.getAnnotation(GeoPointField.class) != null;
}
private static boolean isCompletionField(java.lang.reflect.Field field) {
return field.getType() == Completion.class;
}
}
@@ -1,24 +1,24 @@
/*
* Copyright 2013-2014 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.elasticsearch.core;
import org.elasticsearch.action.search.SearchResponse;
public interface ResultsExtractor<T> {
T extract(SearchResponse response);
}
/*
* Copyright 2013-2014 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.elasticsearch.core;
import org.elasticsearch.action.search.SearchResponse;
public interface ResultsExtractor<T> {
T extract(SearchResponse response);
}
@@ -1,29 +1,29 @@
/*
* Copyright 2013-2014 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.elasticsearch.core;
/**
* ResultsMapper
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
*/
public interface ResultsMapper extends SearchResultMapper, GetResultMapper, MultiGetResultMapper {
EntityMapper getEntityMapper();
}
/*
* Copyright 2013-2014 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.elasticsearch.core;
/**
* ResultsMapper
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
*/
public interface ResultsMapper extends SearchResultMapper, GetResultMapper, MultiGetResultMapper {
EntityMapper getEntityMapper();
}
@@ -1,13 +0,0 @@
package org.springframework.data.elasticsearch.core;
import org.springframework.data.domain.Page;
/**
* @author Artur Konczak
*/
public interface ScrolledPage<T> extends Page<T> {
String getScrollId();
}
@@ -3,14 +3,11 @@ package org.springframework.data.elasticsearch.core.aggregation;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.Aggregations;
import org.springframework.data.elasticsearch.core.FacetedPage;
import org.springframework.data.elasticsearch.core.ScoredPage;
import org.springframework.data.elasticsearch.core.ScrolledPage;
/**
* @author Petar Tahchiev
* @author Sascha Woo
*/
public interface AggregatedPage<T> extends FacetedPage<T>, ScrolledPage<T>, ScoredPage<T> {
public interface AggregatedPage<T> extends FacetedPage<T> {
boolean hasAggregations();
@@ -1,21 +1,8 @@
/*
* Copyright 2017 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.elasticsearch.core.aggregation.impl;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.Aggregations;
@@ -27,77 +14,33 @@ import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
* @author Petar Tahchiev
* @author Artur Konczak
* @author Mohsin Husen
* @author Sascha Woo
*/
public class AggregatedPageImpl<T> extends FacetedPageImpl<T> implements AggregatedPage<T> {
private Aggregations aggregations;
private String scrollId;
private float maxScore;
private Map<String, Aggregation> mapOfAggregations = new HashMap<String, Aggregation>();
public AggregatedPageImpl(List<T> content) {
super(content);
}
public AggregatedPageImpl(List<T> content, float maxScore) {
super(content);
this.maxScore = maxScore;
}
public AggregatedPageImpl(List<T> content, String scrollId) {
super(content);
this.scrollId = scrollId;
}
public AggregatedPageImpl(List<T> content, String scrollId, float maxScore) {
this(content, scrollId);
this.maxScore = maxScore;
}
public AggregatedPageImpl(List<T> content, Pageable pageable, long total) {
super(content, pageable, total);
}
public AggregatedPageImpl(List<T> content, Pageable pageable, long total, float maxScore) {
super(content, pageable, total);
this.maxScore = maxScore;
}
public AggregatedPageImpl(List<T> content, Pageable pageable, long total, String scrollId) {
super(content, pageable, total);
this.scrollId = scrollId;
}
public AggregatedPageImpl(List<T> content, Pageable pageable, long total, String scrollId, float maxScore) {
this(content, pageable, total, scrollId);
this.maxScore = maxScore;
}
public AggregatedPageImpl(List<T> content, Pageable pageable, long total, Aggregations aggregations) {
super(content, pageable, total);
this.aggregations = aggregations;
}
public AggregatedPageImpl(List<T> content, Pageable pageable, long total, Aggregations aggregations, float maxScore) {
this(content, pageable, total, aggregations);
this.maxScore = maxScore;
}
public AggregatedPageImpl(List<T> content, Pageable pageable, long total, Aggregations aggregations,
String scrollId) {
this(content, pageable, total, aggregations);
this.scrollId = scrollId;
}
public AggregatedPageImpl(List<T> content, Pageable pageable, long total, Aggregations aggregations, String scrollId,
float maxScore) {
this(content, pageable, total, aggregations, scrollId);
this.maxScore = maxScore;
if (aggregations != null) {
for (Aggregation aggregation : aggregations) {
mapOfAggregations.put(aggregation.getName(), aggregation);
}
}
}
@Override
public boolean hasAggregations() {
return aggregations != null;
return aggregations != null && mapOfAggregations.size() > 0;
}
@Override
@@ -109,14 +52,4 @@ public class AggregatedPageImpl<T> extends FacetedPageImpl<T> implements Aggrega
public Aggregation getAggregation(String name) {
return aggregations == null ? null : aggregations.get(name);
}
@Override
public String getScrollId() {
return scrollId;
}
@Override
public float getMaxScore() {
return maxScore;
}
}
@@ -11,7 +11,9 @@ import com.fasterxml.jackson.annotation.JsonInclude;
public class Completion {
private String[] input;
private String output;
private Integer weight;
private Object payload;
private Completion() {
//required by mapper to instantiate object
@@ -29,6 +31,22 @@ public class Completion {
this.input = input;
}
public String getOutput() {
return output;
}
public void setOutput(String output) {
this.output = output;
}
public Object getPayload() {
return payload;
}
public void setPayload(Object payload) {
this.payload = payload;
}
public Integer getWeight() {
return weight;
}
@@ -1,77 +1,77 @@
/*
* Copyright 2013 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.elasticsearch.core.convert;
import java.util.Date;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDateTime;
import org.joda.time.ReadableInstant;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import org.springframework.core.convert.converter.Converter;
/**
* DateTimeConverters
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public final class DateTimeConverters {
private static DateTimeFormatter formatter = ISODateTimeFormat.dateTime().withZone(DateTimeZone.UTC);
public enum JodaDateTimeConverter implements Converter<ReadableInstant, String> {
INSTANCE;
@Override
public String convert(ReadableInstant source) {
if (source == null) {
return null;
}
return formatter.print(source);
}
}
public enum JodaLocalDateTimeConverter implements Converter<LocalDateTime, String> {
INSTANCE;
@Override
public String convert(LocalDateTime source) {
if (source == null) {
return null;
}
return formatter.print(source.toDateTime(DateTimeZone.UTC));
}
}
public enum JavaDateConverter implements Converter<Date, String> {
INSTANCE;
@Override
public String convert(Date source) {
if (source == null) {
return null;
}
return formatter.print(source.getTime());
}
}
}
/*
* Copyright 2013 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.elasticsearch.core.convert;
import java.util.Date;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDateTime;
import org.joda.time.ReadableInstant;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import org.springframework.core.convert.converter.Converter;
/**
* DateTimeConverters
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public final class DateTimeConverters {
private static DateTimeFormatter formatter = ISODateTimeFormat.dateTime().withZone(DateTimeZone.UTC);
public enum JodaDateTimeConverter implements Converter<ReadableInstant, String> {
INSTANCE;
@Override
public String convert(ReadableInstant source) {
if (source == null) {
return null;
}
return formatter.print(source);
}
}
public enum JodaLocalDateTimeConverter implements Converter<LocalDateTime, String> {
INSTANCE;
@Override
public String convert(LocalDateTime source) {
if (source == null) {
return null;
}
return formatter.print(source.toDateTime(DateTimeZone.UTC));
}
}
public enum JavaDateConverter implements Converter<Date, String> {
INSTANCE;
@Override
public String convert(Date source) {
if (source == null) {
return null;
}
return formatter.print(source.getTime());
}
}
}
@@ -1,45 +1,45 @@
/*
* Copyright 2013 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.elasticsearch.core.convert;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.mapping.context.MappingContext;
/**
* ElasticsearchConverter
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public interface ElasticsearchConverter {
/**
* Returns the underlying {@link org.springframework.data.mapping.context.MappingContext} used by the converter.
*
* @return never {@literal null}
*/
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> getMappingContext();
/**
* Returns the underlying {@link org.springframework.core.convert.ConversionService} used by the converter.
*
* @return never {@literal null}.
*/
ConversionService getConversionService();
}
/*
* Copyright 2013 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.elasticsearch.core.convert;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.mapping.context.MappingContext;
/**
* ElasticsearchConverter
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public interface ElasticsearchConverter {
/**
* Returns the underlying {@link org.springframework.data.mapping.context.MappingContext} used by the converter.
*
* @return never {@literal null}
*/
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> getMappingContext();
/**
* Returns the underlying {@link org.springframework.core.convert.ConversionService} used by the converter.
*
* @return never {@literal null}.
*/
ConversionService getConversionService();
}
@@ -1,70 +1,70 @@
/*
* Copyright 2013-2017 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.elasticsearch.core.convert;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.util.Assert;
/**
* MappingElasticsearchConverter
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Mark Paluch
*/
public class MappingElasticsearchConverter implements ElasticsearchConverter, ApplicationContextAware {
private final MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext;
private final GenericConversionService conversionService;
@SuppressWarnings("unused")
private ApplicationContext applicationContext;
public MappingElasticsearchConverter(
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext) {
Assert.notNull(mappingContext, "MappingContext must not be null!");
this.mappingContext = mappingContext;
this.conversionService = new DefaultConversionService();
}
@Override
public MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> getMappingContext() {
return mappingContext;
}
@Override
public ConversionService getConversionService() {
return this.conversionService;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
if (mappingContext instanceof ApplicationContextAware) {
((ApplicationContextAware) mappingContext).setApplicationContext(applicationContext);
}
}
}
/*
* Copyright 2013-2017 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.elasticsearch.core.convert;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.util.Assert;
/**
* MappingElasticsearchConverter
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Mark Paluch
*/
public class MappingElasticsearchConverter implements ElasticsearchConverter, ApplicationContextAware {
private final MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext;
private final GenericConversionService conversionService;
@SuppressWarnings("unused")
private ApplicationContext applicationContext;
public MappingElasticsearchConverter(
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext) {
Assert.notNull(mappingContext, "MappingContext must not be null!");
this.mappingContext = mappingContext;
this.conversionService = new DefaultConversionService();
}
@Override
public MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> getMappingContext() {
return mappingContext;
}
@Override
public ConversionService getConversionService() {
return this.conversionService;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
if (mappingContext instanceof ApplicationContextAware) {
((ApplicationContextAware) mappingContext).setApplicationContext(applicationContext);
}
}
}
@@ -16,13 +16,14 @@
package org.springframework.data.elasticsearch.core.facet.request;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramBuilder;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* @author Artur Konczak
@@ -53,19 +54,19 @@ public class HistogramFacetRequest extends AbstractFacetRequest {
public AbstractAggregationBuilder getFacet() {
Assert.notNull(getName(), "Facet name can't be a null !!!");
Assert.isTrue(!StringUtils.isEmpty(field), "Please select field on which to build the facet !!!");
Assert.isTrue(StringUtils.isNotBlank(field), "Please select field on which to build the facet !!!");
Assert.isTrue(interval > 0, "Please provide interval as positive value greater them zero !!!");
DateHistogramAggregationBuilder dateHistogramBuilder = AggregationBuilders.dateHistogram(getName());
DateHistogramBuilder dateHistogramBuilder = AggregationBuilders.dateHistogram(getName());
dateHistogramBuilder.field(field);
if (timeUnit != null) {
dateHistogramBuilder.dateHistogramInterval(timeUnit);
dateHistogramBuilder.interval(timeUnit);
} else {
dateHistogramBuilder.interval(interval);
}
dateHistogramBuilder.subAggregation(AggregationBuilders.extendedStats(INTERNAL_STATS).field(field));
dateHistogramBuilder.subAggregation(AggregationBuilders.extendedStats(INTERNAL_STATS));
return dateHistogramBuilder;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014 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.
@@ -19,12 +19,13 @@ package org.springframework.data.elasticsearch.core.facet.request;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.range.RangeAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.range.RangeBuilder;
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Range facet for numeric fields
@@ -40,7 +41,7 @@ public class RangeFacetRequest extends AbstractFacetRequest {
private String keyField;
private String valueField;
private List<Entry> entries = new ArrayList<>();
private List<Entry> entries = new ArrayList<Entry>();
public RangeFacetRequest(String name) {
super(name);
@@ -75,17 +76,16 @@ public class RangeFacetRequest extends AbstractFacetRequest {
public AbstractAggregationBuilder getFacet() {
Assert.notNull(getName(), "Facet name can't be a null !!!");
RangeAggregationBuilder rangeBuilder = AggregationBuilders.range(getName());
final String field = !StringUtils.isEmpty(keyField) ? keyField : this.field;
rangeBuilder.field(field);
RangeBuilder rangeBuilder = AggregationBuilders.range(getName());
rangeBuilder.field(StringUtils.isNotBlank(keyField) ? keyField : field );
for (Entry entry : entries) {
DoubleEntry doubleEntry = (DoubleEntry) entry;
rangeBuilder.addRange(validateValue(doubleEntry.getFrom(), Double.NEGATIVE_INFINITY), validateValue(doubleEntry.getTo(), Double.POSITIVE_INFINITY));
}
rangeBuilder.subAggregation(AggregationBuilders.extendedStats(INTERNAL_STATS).field(field));
if(!StringUtils.isEmpty(valueField)){
rangeBuilder.subAggregation(AggregationBuilders.extendedStats(INTERNAL_STATS));
if(StringUtils.isNotBlank(valueField)){
rangeBuilder.subAggregation(AggregationBuilders.sum(RANGE_INTERNAL_SUM).field(valueField));
}
@@ -16,11 +16,12 @@
package org.springframework.data.elasticsearch.core.facet.request;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* @author Petar Tahchiev
@@ -46,7 +47,7 @@ public class StatisticalFacetRequest extends AbstractFacetRequest {
public AbstractAggregationBuilder getFacet() {
Assert.notNull(getName(), "Facet name can't be a null !!!");
Assert.isTrue(!StringUtils.isEmpty(field) && fields == null, "Please select field or fields on which to build the facets !!!");
Assert.isTrue(StringUtils.isNotBlank(field) && fields == null, "Please select field or fields on which to build the facets !!!");
return AggregationBuilders.extendedStats(getName()).field(field);
}
}
@@ -16,22 +16,20 @@
package org.springframework.data.elasticsearch.core.facet.request;
import org.apache.lucene.util.automaton.RegExp;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.BucketOrder;
import org.elasticsearch.search.aggregations.bucket.terms.IncludeExclude;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsBuilder;
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
* Term facet
*
* @author Artur Konczak
* @author Ilkang Na
*/
@Deprecated
public class TermFacetRequest extends AbstractFacetRequest {
@@ -48,8 +46,8 @@ public class TermFacetRequest extends AbstractFacetRequest {
}
public void setFields(String... fields) {
Assert.isTrue(!ObjectUtils.isEmpty(fields), "Term agg need one field only");
Assert.isTrue(fields.length == 1, "Term agg need one field only");
Assert.isTrue(ArrayUtils.isNotEmpty(fields), "Term agg need one field only");
Assert.isTrue(ArrayUtils.getLength(fields) == 1, "Term agg need one field only");
this.fields = fields;
}
@@ -77,33 +75,33 @@ public class TermFacetRequest extends AbstractFacetRequest {
@Override
public AbstractAggregationBuilder getFacet() {
Assert.notEmpty(fields, "Please select at last one field !!!");
final TermsAggregationBuilder termsBuilder = AggregationBuilders.terms(getName()).field(fields[0]).size(this.size);
TermsBuilder termsBuilder = AggregationBuilders.terms(getName()).field(fields[0]).size(this.size);
switch (order) {
case descTerm:
termsBuilder.order(BucketOrder.key(false));
termsBuilder.order(Terms.Order.term(false));
break;
case ascTerm:
termsBuilder.order(BucketOrder.key(true));
termsBuilder.order(Terms.Order.term(true));
break;
case descCount:
termsBuilder.order(BucketOrder.count(false));
termsBuilder.order(Terms.Order.count(false));
break;
default:
termsBuilder.order(BucketOrder.count(true));
termsBuilder.order(Terms.Order.count(true));
}
if (!ObjectUtils.isEmpty(excludeTerms)) {
termsBuilder.includeExclude(new IncludeExclude(null, excludeTerms));
if (ArrayUtils.isNotEmpty(excludeTerms)) {
termsBuilder.exclude(excludeTerms);
}
if (allTerms) {
termsBuilder.size(Integer.MAX_VALUE);
}
if (!StringUtils.isEmpty(regex)) {
termsBuilder.includeExclude(new IncludeExclude(new RegExp(regex), null));
if (StringUtils.isNotBlank(regex)) {
termsBuilder.include(regex);
}
return termsBuilder;
}
}
}
@@ -1,8 +1,10 @@
package org.springframework.data.elasticsearch.core.geo;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
@@ -30,15 +32,39 @@ public class CustomGeoModule extends SimpleModule {
}
class PointSerializer extends JsonSerializer<Point> {
@Override
public void serialize(Point value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
public void serialize(Point value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
gen.writeObject(GeoPoint.fromPoint(value));
// gen.writeStartObject();
// gen.writeNumberField("lat", value.getY());
// gen.writeNumberField("lon", value.getX());
// gen.writeEndObject();
}
}
class PointDeserializer extends JsonDeserializer<Point> {
@Override
public Point deserialize(JsonParser p, DeserializationContext context) throws IOException {
return GeoPoint.toPoint(p.readValueAs(GeoPoint.class));
public Point deserialize(JsonParser p, DeserializationContext context) throws IOException, JsonProcessingException {
GeoPoint point = p.readValueAs(GeoPoint.class);
// Double lat = null;
// Double lon = null;
// //skipp field name
// p.nextFieldName();
// if ("lat".equals(p.getCurrentName())) {
// //get value
// p.nextFieldName();
// lat = p.getDoubleValue();
// p.nextFieldName();
// }
// if ("lon".equals(p.getCurrentName())) {
// //get value
// p.nextFieldName();
// lon = p.getDoubleValue();
// }
// return new Point(lon, lat);
return GeoPoint.toPoint(point);
}
}
@@ -1,75 +1,52 @@
/*
* Copyright 2013-2018 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.elasticsearch.core.mapping;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.lang.Nullable;
/**
* ElasticsearchPersistentEntity
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Mark Paluch
* @author Sascha Woo
* @author Oliver Gierke
*/
public interface ElasticsearchPersistentEntity<T> extends PersistentEntity<T, ElasticsearchPersistentProperty> {
String getIndexName();
String getIndexType();
short getShards();
short getReplicas();
boolean isUseServerConfiguration();
String getRefreshInterval();
String getIndexStoreType();
ElasticsearchPersistentProperty getVersionProperty();
String getParentType();
ElasticsearchPersistentProperty getParentIdProperty();
String settingPath();
boolean isCreateIndexAndMapping();
/**
* Returns whether the {@link ElasticsearchPersistentEntity} has an score property. If this call returns
* {@literal true}, {@link #getScoreProperty()} will return a non-{@literal null} value.
*
* @return false when {@link ElasticsearchPersistentEntity} does not define a score property.
* @since 3.1
*/
boolean hasScoreProperty();
/**
* Returns the score property of the {@link ElasticsearchPersistentEntity}. Can be {@literal null} in case no score
* property is available on the entity.
*
* @return the score {@link ElasticsearchPersistentProperty} of the {@link PersistentEntity} or {@literal null} if not
* defined.
* @since 3.1
*/
@Nullable
ElasticsearchPersistentProperty getScoreProperty();
}
/*
* Copyright 2013-2014 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.elasticsearch.core.mapping;
import org.springframework.data.mapping.PersistentEntity;
/**
* ElasticsearchPersistentEntity
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public interface ElasticsearchPersistentEntity<T> extends PersistentEntity<T, ElasticsearchPersistentProperty> {
String getIndexName();
String getIndexType();
short getShards();
short getReplicas();
boolean isUseServerConfiguration();
String getRefreshInterval();
String getIndexStoreType();
ElasticsearchPersistentProperty getVersionProperty();
String getParentType();
ElasticsearchPersistentProperty getParentIdProperty();
String settingPath();
boolean isCreateIndexAndMapping();
}
@@ -1,65 +1,40 @@
/*
* Copyright 2013-2018 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.elasticsearch.core.mapping;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.mapping.PersistentProperty;
/**
* ElasticsearchPersistentProperty
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Sascha Woo
* @author Oliver Gierke
*/
public interface ElasticsearchPersistentProperty extends PersistentProperty<ElasticsearchPersistentProperty> {
String getFieldName();
/**
* Returns whether the current property is a <em>potential</em> score property of the owning
* {@link ElasticsearchPersistentEntity}. This method is mainly used by {@link ElasticsearchPersistentEntity}
* implementation to discover score property candidates on {@link ElasticsearchPersistentEntity} creation you should
* rather call {@link ElasticsearchPersistentEntity#isScoreProperty(PersistentProperty)} to determine whether the
* current property is the score property of that {@link ElasticsearchPersistentEntity} under consideration.
*
* @return
* @since 3.1
*/
boolean isScoreProperty();
/**
* Returns whether the current property is a <em>potential</em> parent property of the owning
* {@link ElasticsearchPersistentEntity}. This method is mainly used by {@link ElasticsearchPersistentEntity}
* implementation to discover parent property candidates on {@link ElasticsearchPersistentEntity} creation you should
* rather call {@link ElasticsearchPersistentEntity#isParentProperty()} to determine whether the current property is
* the parent property of that {@link ElasticsearchPersistentEntity} under consideration.
*
* @return
* @since 3.1
*/
boolean isParentProperty();
public enum PropertyToFieldNameConverter implements Converter<ElasticsearchPersistentProperty, String> {
INSTANCE;
public String convert(ElasticsearchPersistentProperty source) {
return source.getFieldName();
}
}
}
/*
* Copyright 2013 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.elasticsearch.core.mapping;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.mapping.PersistentProperty;
/**
* ElasticsearchPersistentProperty
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public interface ElasticsearchPersistentProperty extends PersistentProperty<ElasticsearchPersistentProperty> {
String getFieldName();
public enum PropertyToFieldNameConverter implements Converter<ElasticsearchPersistentProperty, String> {
INSTANCE;
public String convert(ElasticsearchPersistentProperty source) {
return source.getFieldName();
}
}
}
@@ -1,58 +1,60 @@
/*
* Copyright 2013-2017 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.elasticsearch.core.mapping;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.mapping.context.AbstractMappingContext;
import org.springframework.data.mapping.model.Property;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.util.TypeInformation;
/**
* SimpleElasticsearchMappingContext
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Mark Paluch
*/
public class SimpleElasticsearchMappingContext extends
AbstractMappingContext<SimpleElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> implements ApplicationContextAware {
private ApplicationContext context;
@Override
protected <T> SimpleElasticsearchPersistentEntity<?> createPersistentEntity(TypeInformation<T> typeInformation) {
final SimpleElasticsearchPersistentEntity<T> persistentEntity = new SimpleElasticsearchPersistentEntity<>(
typeInformation);
if (context != null) {
persistentEntity.setApplicationContext(context);
}
return persistentEntity;
}
@Override
protected ElasticsearchPersistentProperty createPersistentProperty(Property property,
SimpleElasticsearchPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
return new SimpleElasticsearchPersistentProperty(property, owner, simpleTypeHolder);
}
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
this.context = context;
}
}
/*
* Copyright 2013 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.elasticsearch.core.mapping;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.mapping.context.AbstractMappingContext;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.util.TypeInformation;
/**
* SimpleElasticsearchMappingContext
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class SimpleElasticsearchMappingContext extends
AbstractMappingContext<SimpleElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> implements ApplicationContextAware {
private ApplicationContext context;
@Override
protected <T> SimpleElasticsearchPersistentEntity<?> createPersistentEntity(TypeInformation<T> typeInformation) {
final SimpleElasticsearchPersistentEntity<T> persistentEntity =
new SimpleElasticsearchPersistentEntity<T>(typeInformation);
if (context != null) {
persistentEntity.setApplicationContext(context);
}
return persistentEntity;
}
@Override
protected ElasticsearchPersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor,
SimpleElasticsearchPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
return new SimpleElasticsearchPersistentProperty(field, descriptor, owner, simpleTypeHolder);
}
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
this.context = context;
}
}
@@ -1,212 +1,170 @@
/*
* Copyright 2013-2017 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.elasticsearch.core.mapping;
import static org.springframework.util.StringUtils.*;
import java.util.Locale;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.expression.BeanFactoryAccessor;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Parent;
import org.springframework.data.elasticsearch.annotations.Setting;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.mapping.model.BasicPersistentEntity;
import org.springframework.data.mapping.model.PersistentPropertyAccessorFactory;
import org.springframework.data.util.TypeInformation;
import org.springframework.expression.Expression;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Elasticsearch specific {@link org.springframework.data.mapping.PersistentEntity} implementation holding
*
* @param <T>
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Mark Paluch
* @author Sascha Woo
*/
public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntity<T, ElasticsearchPersistentProperty>
implements ElasticsearchPersistentEntity<T>, ApplicationContextAware {
private final StandardEvaluationContext context;
private final SpelExpressionParser parser;
private String indexName;
private String indexType;
private boolean useServerConfiguration;
private short shards;
private short replicas;
private String refreshInterval;
private String indexStoreType;
private String parentType;
private ElasticsearchPersistentProperty parentIdProperty;
private ElasticsearchPersistentProperty scoreProperty;
private String settingPath;
private boolean createIndexAndMapping;
public SimpleElasticsearchPersistentEntity(TypeInformation<T> typeInformation) {
super(typeInformation);
this.context = new StandardEvaluationContext();
this.parser = new SpelExpressionParser();
Class<T> clazz = typeInformation.getType();
if (clazz.isAnnotationPresent(Document.class)) {
Document document = clazz.getAnnotation(Document.class);
Assert.hasText(document.indexName(),
" Unknown indexName. Make sure the indexName is defined. e.g @Document(indexName=\"foo\")");
this.indexName = document.indexName();
this.indexType = hasText(document.type()) ? document.type() : clazz.getSimpleName().toLowerCase(Locale.ENGLISH);
this.useServerConfiguration = document.useServerConfiguration();
this.shards = document.shards();
this.replicas = document.replicas();
this.refreshInterval = document.refreshInterval();
this.indexStoreType = document.indexStoreType();
this.createIndexAndMapping = document.createIndex();
}
if (clazz.isAnnotationPresent(Setting.class)) {
this.settingPath = typeInformation.getType().getAnnotation(Setting.class).settingPath();
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context.addPropertyAccessor(new BeanFactoryAccessor());
context.setBeanResolver(new BeanFactoryResolver(applicationContext));
context.setRootObject(applicationContext);
}
@Override
public String getIndexName() {
Expression expression = parser.parseExpression(indexName, ParserContext.TEMPLATE_EXPRESSION);
return expression.getValue(context, String.class);
}
@Override
public String getIndexType() {
Expression expression = parser.parseExpression(indexType, ParserContext.TEMPLATE_EXPRESSION);
return expression.getValue(context, String.class);
}
@Override
public String getIndexStoreType() {
return indexStoreType;
}
@Override
public short getShards() {
return shards;
}
@Override
public short getReplicas() {
return replicas;
}
@Override
public boolean isUseServerConfiguration() {
return useServerConfiguration;
}
@Override
public String getRefreshInterval() {
return refreshInterval;
}
@Override
public String getParentType() {
return parentType;
}
@Override
public ElasticsearchPersistentProperty getParentIdProperty() {
return parentIdProperty;
}
@Override
public String settingPath() {
return settingPath;
}
@Override
public boolean isCreateIndexAndMapping() {
return createIndexAndMapping;
}
@Override
public boolean hasScoreProperty() {
return scoreProperty != null;
}
@Nullable
@Override
public ElasticsearchPersistentProperty getScoreProperty() {
return scoreProperty;
}
@Override
public void addPersistentProperty(ElasticsearchPersistentProperty property) {
super.addPersistentProperty(property);
if (property.isParentProperty()) {
ElasticsearchPersistentProperty parentProperty = this.parentIdProperty;
if (parentProperty != null) {
throw new MappingException(
String.format("Attempt to add parent property %s but already have property %s registered "
+ "as parent property. Check your mapping configuration!", property.getField(), parentProperty.getField()));
}
Parent parentAnnotation = property.findAnnotation(Parent.class);
this.parentIdProperty = property;
this.parentType = parentAnnotation.type();
}
if (property.isScoreProperty()) {
ElasticsearchPersistentProperty scoreProperty = this.scoreProperty;
if (scoreProperty != null) {
throw new MappingException(
String.format("Attempt to add score property %s but already have property %s registered "
+ "as score property. Check your mapping configuration!", property.getField(), scoreProperty.getField()));
}
this.scoreProperty = property;
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.model.BasicPersistentEntity#setPersistentPropertyAccessorFactory(org.springframework.data.mapping.model.PersistentPropertyAccessorFactory)
*/
@Override
public void setPersistentPropertyAccessorFactory(PersistentPropertyAccessorFactory factory) {
// Do nothing to avoid the usage of ClassGeneratingPropertyAccessorFactory for now
// DATACMNS-1322 switches to proper immutability behavior which Spring Data Elasticsearch
// cannot yet implement
}
}
/*
* Copyright 2013-2014 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.elasticsearch.core.mapping;
import static org.springframework.util.StringUtils.*;
import java.util.Locale;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.expression.BeanFactoryAccessor;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Parent;
import org.springframework.data.elasticsearch.annotations.Setting;
import org.springframework.data.mapping.model.BasicPersistentEntity;
import org.springframework.data.util.TypeInformation;
import org.springframework.expression.Expression;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.Assert;
/**
* Elasticsearch specific {@link org.springframework.data.mapping.PersistentEntity} implementation holding
*
* @param <T>
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntity<T, ElasticsearchPersistentProperty>
implements ElasticsearchPersistentEntity<T>, ApplicationContextAware {
private final StandardEvaluationContext context;
private final SpelExpressionParser parser;
private String indexName;
private String indexType;
private boolean useServerConfiguration;
private short shards;
private short replicas;
private String refreshInterval;
private String indexStoreType;
private String parentType;
private ElasticsearchPersistentProperty parentIdProperty;
private String settingPath;
private boolean createIndexAndMapping;
public SimpleElasticsearchPersistentEntity(TypeInformation<T> typeInformation) {
super(typeInformation);
this.context = new StandardEvaluationContext();
this.parser = new SpelExpressionParser();
Class<T> clazz = typeInformation.getType();
if (clazz.isAnnotationPresent(Document.class)) {
Document document = clazz.getAnnotation(Document.class);
Assert.hasText(document.indexName(),
" Unknown indexName. Make sure the indexName is defined. e.g @Document(indexName=\"foo\")");
this.indexName = document.indexName();
this.indexType = hasText(document.type()) ? document.type() : clazz.getSimpleName().toLowerCase(Locale.ENGLISH);
this.useServerConfiguration = document.useServerConfiguration();
this.shards = document.shards();
this.replicas = document.replicas();
this.refreshInterval = document.refreshInterval();
this.indexStoreType = document.indexStoreType();
this.createIndexAndMapping = document.createIndex();
}
if (clazz.isAnnotationPresent(Setting.class)) {
this.settingPath = typeInformation.getType().getAnnotation(Setting.class).settingPath();
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context.addPropertyAccessor(new BeanFactoryAccessor());
context.setBeanResolver(new BeanFactoryResolver(applicationContext));
context.setRootObject(applicationContext);
}
@Override
public String getIndexName() {
Expression expression = parser.parseExpression(indexName, ParserContext.TEMPLATE_EXPRESSION);
return expression.getValue(context, String.class);
}
@Override
public String getIndexType() {
Expression expression = parser.parseExpression(indexType, ParserContext.TEMPLATE_EXPRESSION);
return expression.getValue(context, String.class);
}
@Override
public String getIndexStoreType() {
return indexStoreType;
}
@Override
public short getShards() {
return shards;
}
@Override
public short getReplicas() {
return replicas;
}
@Override
public boolean isUseServerConfiguration() {
return useServerConfiguration;
}
@Override
public String getRefreshInterval() {
return refreshInterval;
}
@Override
public String getParentType() {
return parentType;
}
@Override
public ElasticsearchPersistentProperty getParentIdProperty() {
return parentIdProperty;
}
@Override
public String settingPath() {
return settingPath;
}
@Override
public boolean isCreateIndexAndMapping() {
return createIndexAndMapping;
}
@Override
public void addPersistentProperty(ElasticsearchPersistentProperty property) {
super.addPersistentProperty(property);
if (property.getField() != null) {
Parent parent = property.getField().getAnnotation(Parent.class);
if (parent != null) {
Assert.isNull(this.parentIdProperty, "Only one field can hold a @Parent annotation");
Assert.isNull(this.parentType, "Only one field can hold a @Parent annotation");
Assert.isTrue(property.getType() == String.class, "Parent ID property should be String");
this.parentIdProperty = property;
this.parentType = parent.type();
}
}
if (property.isVersionProperty()) {
Assert.isTrue(property.getType() == Long.class, "Version property should be Long");
}
}
}
@@ -1,124 +1,65 @@
/*
* Copyright 2013-2018 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.elasticsearch.core.mapping;
import java.util.Arrays;
import java.util.List;
import org.springframework.data.elasticsearch.annotations.Parent;
import org.springframework.data.elasticsearch.annotations.Score;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
import org.springframework.data.mapping.model.Property;
import org.springframework.data.mapping.model.SimpleTypeHolder;
/**
* Elasticsearch specific {@link org.springframework.data.mapping.PersistentProperty} implementation processing
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Mark Paluch
* @author Sascha Woo
* @author Oliver Gierke
*/
public class SimpleElasticsearchPersistentProperty extends
AnnotationBasedPersistentProperty<ElasticsearchPersistentProperty> implements ElasticsearchPersistentProperty {
private static final List<String> SUPPORTED_ID_PROPERTY_NAMES = Arrays.asList("id", "document");
private final boolean isScore;
private final boolean isParent;
private final boolean isId;
public SimpleElasticsearchPersistentProperty(Property property,
PersistentEntity<?, ElasticsearchPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
super(property, owner, simpleTypeHolder);
this.isId = super.isIdProperty() || SUPPORTED_ID_PROPERTY_NAMES.contains(getFieldName());
this.isScore = isAnnotationPresent(Score.class);
this.isParent = isAnnotationPresent(Parent.class);
if (isVersionProperty() && getType() != Long.class) {
throw new MappingException(String.format("Version property %s must be of type Long!", property.getName()));
}
if (isScore && !Arrays.asList(Float.TYPE, Float.class).contains(getType())) {
throw new MappingException(
String.format("Score property %s must be either of type float or Float!", property.getName()));
}
if (isParent && getType() != String.class) {
throw new MappingException(String.format("Parent property %s must be of type String!", property.getName()));
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty#getFieldName()
*/
@Override
public String getFieldName() {
return getProperty().getName();
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.model.AnnotationBasedPersistentProperty#isIdProperty()
*/
@Override
public boolean isIdProperty() {
return isId;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.model.AbstractPersistentProperty#createAssociation()
*/
@Override
protected Association<ElasticsearchPersistentProperty> createAssociation() {
return null;
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty#isScoreProperty()
*/
@Override
public boolean isScoreProperty() {
return isScore;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.model.AbstractPersistentProperty#isImmutable()
*/
@Override
public boolean isImmutable() {
return false;
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty#isParentProperty()
*/
@Override
public boolean isParentProperty() {
return isParent;
}
}
/*
* Copyright 2013 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.elasticsearch.core.mapping;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Set;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
import org.springframework.data.mapping.model.SimpleTypeHolder;
/**
* Elasticsearch specific {@link org.springframework.data.mapping.PersistentProperty} implementation processing
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class SimpleElasticsearchPersistentProperty extends
AnnotationBasedPersistentProperty<ElasticsearchPersistentProperty> implements ElasticsearchPersistentProperty {
private static final Set<Class<?>> SUPPORTED_ID_TYPES = new HashSet<Class<?>>();
private static final Set<String> SUPPORTED_ID_PROPERTY_NAMES = new HashSet<String>();
static {
SUPPORTED_ID_TYPES.add(String.class);
SUPPORTED_ID_PROPERTY_NAMES.add("id");
SUPPORTED_ID_PROPERTY_NAMES.add("documentId");
}
public SimpleElasticsearchPersistentProperty(Field field, PropertyDescriptor propertyDescriptor,
PersistentEntity<?, ElasticsearchPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
super(field, propertyDescriptor, owner, simpleTypeHolder);
}
@Override
public String getFieldName() {
return field.getName();
}
@Override
public boolean isIdProperty() {
return super.isIdProperty() || (field != null ? SUPPORTED_ID_PROPERTY_NAMES.contains(getFieldName()) : false);
}
@Override
protected Association<ElasticsearchPersistentProperty> createAssociation() {
return null;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2018 the original author or authors.
* Copyright 2013-2017 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.
@@ -15,14 +15,11 @@
*/
package org.springframework.data.elasticsearch.core.query;
import static java.util.Collections.*;
import static java.util.Collections.addAll;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.support.IndicesOptions;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.util.Assert;
@@ -33,23 +30,19 @@ import org.springframework.util.Assert;
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Mark Paluch
* @author Alen Turkovic
* @author Sascha Woo
*/
abstract class AbstractQuery implements Query {
protected Pageable pageable = DEFAULT_PAGE;
protected Sort sort;
protected List<String> indices = new ArrayList<>();
protected List<String> types = new ArrayList<>();
protected List<String> fields = new ArrayList<>();
protected List<String> indices = new ArrayList<String>();
protected List<String> types = new ArrayList<String>();
protected List<String> fields = new ArrayList<String>();
protected SourceFilter sourceFilter;
protected float minScore;
protected Collection<String> ids;
protected String route;
protected SearchType searchType = SearchType.DFS_QUERY_THEN_FETCH;
protected IndicesOptions indicesOptions;
protected boolean trackScores;
@Override
public Sort getSort() {
@@ -156,31 +149,4 @@ abstract class AbstractQuery implements Query {
public SearchType getSearchType() {
return searchType;
}
public IndicesOptions getIndicesOptions() {
return indicesOptions;
}
public void setIndicesOptions(IndicesOptions indicesOptions) {
this.indicesOptions = indicesOptions;
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.core.query.Query#getTrackScores()
*/
@Override
public boolean getTrackScores() {
return trackScores;
}
/**
* Configures whether to track scores.
*
* @param trackScores
* @since 3.1
*/
public void setTrackScores(boolean trackScores) {
this.trackScores = trackScores;
}
}
@@ -1,81 +1,81 @@
/*
* Copyright 2013-2014 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.elasticsearch.core.query;
import java.util.Map;
import org.elasticsearch.index.query.QueryBuilder;
/**
* @author Mohsin Husen
*/
public class AliasBuilder {
private String indexName;
private String aliasName;
private QueryBuilder filterBuilder;
private Map<String, Object> filter;
private String searchRouting;
private String indexRouting;
private String routing;
public AliasBuilder withIndexName(String indexName) {
this.indexName = indexName;
return this;
}
public AliasBuilder withAliasName(String aliasName) {
this.aliasName = aliasName;
return this;
}
public AliasBuilder withFilterBuilder(QueryBuilder filterBuilder) {
this.filterBuilder = filterBuilder;
return this;
}
public AliasBuilder withFilter(Map<String, Object> filter) {
this.filter = filter;
return this;
}
public AliasBuilder withSearchRouting(String searchRouting) {
this.searchRouting = searchRouting;
return this;
}
public AliasBuilder withIndexRouting(String indexRouting) {
this.indexRouting = indexRouting;
return this;
}
public AliasBuilder withRouting(String routing) {
this.routing = routing;
return this;
}
public AliasQuery build() {
AliasQuery aliasQuery = new AliasQuery();
aliasQuery.setIndexName(indexName);
aliasQuery.setAliasName(aliasName);
aliasQuery.setFilterBuilder(filterBuilder);
aliasQuery.setFilter(filter);
aliasQuery.setSearchRouting(searchRouting);
aliasQuery.setIndexRouting(indexRouting);
aliasQuery.setRouting(routing);
return aliasQuery;
}
}
/*
* Copyright 2013-2014 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.elasticsearch.core.query;
import java.util.Map;
import org.elasticsearch.index.query.QueryBuilder;
/**
* @author Mohsin Husen
*/
public class AliasBuilder {
private String indexName;
private String aliasName;
private QueryBuilder filterBuilder;
private Map<String, Object> filter;
private String searchRouting;
private String indexRouting;
private String routing;
public AliasBuilder withIndexName(String indexName) {
this.indexName = indexName;
return this;
}
public AliasBuilder withAliasName(String aliasName) {
this.aliasName = aliasName;
return this;
}
public AliasBuilder withFilterBuilder(QueryBuilder filterBuilder) {
this.filterBuilder = filterBuilder;
return this;
}
public AliasBuilder withFilter(Map<String, Object> filter) {
this.filter = filter;
return this;
}
public AliasBuilder withSearchRouting(String searchRouting) {
this.searchRouting = searchRouting;
return this;
}
public AliasBuilder withIndexRouting(String indexRouting) {
this.indexRouting = indexRouting;
return this;
}
public AliasBuilder withRouting(String routing) {
this.routing = routing;
return this;
}
public AliasQuery build() {
AliasQuery aliasQuery = new AliasQuery();
aliasQuery.setIndexName(indexName);
aliasQuery.setAliasName(aliasName);
aliasQuery.setFilterBuilder(filterBuilder);
aliasQuery.setFilter(filter);
aliasQuery.setSearchRouting(searchRouting);
aliasQuery.setIndexRouting(indexRouting);
aliasQuery.setRouting(routing);
return aliasQuery;
}
}
@@ -1,92 +1,92 @@
/*
* Copyright 2013-2014 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.elasticsearch.core.query;
import java.util.Map;
import org.elasticsearch.index.query.QueryBuilder;
/**
* AliasQuery is useful for creating new alias or deleting existing ones
*
* @author Mohsin Husen
*/
public class AliasQuery {
private String indexName;
private String aliasName;
private QueryBuilder filterBuilder;
private Map<String, Object> filter;
private String searchRouting;
private String indexRouting;
private String routing;
public String getIndexName() {
return indexName;
}
public void setIndexName(String indexName) {
this.indexName = indexName;
}
public String getAliasName() {
return aliasName;
}
public void setAliasName(String aliasName) {
this.aliasName = aliasName;
}
public QueryBuilder getFilterBuilder() {
return filterBuilder;
}
public void setFilterBuilder(QueryBuilder filterBuilder) {
this.filterBuilder = filterBuilder;
}
public Map<String, Object> getFilter() {
return filter;
}
public void setFilter(Map<String, Object> filter) {
this.filter = filter;
}
public String getSearchRouting() {
return searchRouting;
}
public void setSearchRouting(String searchRouting) {
this.searchRouting = searchRouting;
}
public String getIndexRouting() {
return indexRouting;
}
public void setIndexRouting(String indexRouting) {
this.indexRouting = indexRouting;
}
public String getRouting() {
return routing;
}
public void setRouting(String routing) {
this.routing = routing;
}
}
/*
* Copyright 2013-2014 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.elasticsearch.core.query;
import java.util.Map;
import org.elasticsearch.index.query.QueryBuilder;
/**
* AliasQuery is useful for creating new alias or deleting existing ones
*
* @author Mohsin Husen
*/
public class AliasQuery {
private String indexName;
private String aliasName;
private QueryBuilder filterBuilder;
private Map<String, Object> filter;
private String searchRouting;
private String indexRouting;
private String routing;
public String getIndexName() {
return indexName;
}
public void setIndexName(String indexName) {
this.indexName = indexName;
}
public String getAliasName() {
return aliasName;
}
public void setAliasName(String aliasName) {
this.aliasName = aliasName;
}
public QueryBuilder getFilterBuilder() {
return filterBuilder;
}
public void setFilterBuilder(QueryBuilder filterBuilder) {
this.filterBuilder = filterBuilder;
}
public Map<String, Object> getFilter() {
return filter;
}
public void setFilter(Map<String, Object> filter) {
this.filter = filter;
}
public String getSearchRouting() {
return searchRouting;
}
public void setSearchRouting(String searchRouting) {
this.searchRouting = searchRouting;
}
public String getIndexRouting() {
return indexRouting;
}
public void setIndexRouting(String indexRouting) {
this.indexRouting = indexRouting;
}
public String getRouting() {
return routing;
}
public void setRouting(String routing) {
this.routing = routing;
}
}
File diff suppressed because it is too large Load Diff
@@ -1,82 +1,80 @@
/*
* Copyright 2013-2017 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.elasticsearch.core.query;
import org.springframework.data.domain.Pageable;
import org.springframework.util.Assert;
/**
* CriteriaQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Mark Paluch
*/
public class CriteriaQuery extends AbstractQuery {
private Criteria criteria;
private CriteriaQuery() {}
public CriteriaQuery(Criteria criteria) {
this(criteria, Pageable.unpaged());
}
public CriteriaQuery(Criteria criteria, Pageable pageable) {
Assert.notNull(criteria, "Criteria must not be null!");
Assert.notNull(pageable, "Pageable must not be null!");
this.criteria = criteria;
this.pageable = pageable;
this.addSort(pageable.getSort());
}
public static final Query fromQuery(CriteriaQuery source) {
return fromQuery(source, new CriteriaQuery());
}
public static <T extends CriteriaQuery> T fromQuery(CriteriaQuery source, T destination) {
if (source == null || destination == null) {
return null;
}
if (source.getCriteria() != null) {
destination.addCriteria(source.getCriteria());
}
if (source.getSort() != null) {
destination.addSort(source.getSort());
}
return destination;
}
@SuppressWarnings("unchecked")
public final <T extends CriteriaQuery> T addCriteria(Criteria criteria) {
Assert.notNull(criteria, "Cannot add null criteria.");
if (this.criteria == null) {
this.criteria = criteria;
} else {
this.criteria.and(criteria);
}
return (T) this;
}
public Criteria getCriteria() {
return this.criteria;
}
}
/*
* Copyright 2013 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.elasticsearch.core.query;
import org.springframework.data.domain.Pageable;
import org.springframework.util.Assert;
/**
* CriteriaQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class CriteriaQuery extends AbstractQuery {
private Criteria criteria;
private CriteriaQuery() {
}
public CriteriaQuery(Criteria criteria) {
this(criteria, null);
}
public CriteriaQuery(Criteria criteria, Pageable pageable) {
this.criteria = criteria;
this.pageable = pageable;
if (pageable != null) {
this.addSort(pageable.getSort());
}
}
public static final Query fromQuery(CriteriaQuery source) {
return fromQuery(source, new CriteriaQuery());
}
public static <T extends CriteriaQuery> T fromQuery(CriteriaQuery source, T destination) {
if (source == null || destination == null) {
return null;
}
if (source.getCriteria() != null) {
destination.addCriteria(source.getCriteria());
}
if (source.getSort() != null) {
destination.addSort(source.getSort());
}
return destination;
}
@SuppressWarnings("unchecked")
public final <T extends CriteriaQuery> T addCriteria(Criteria criteria) {
Assert.notNull(criteria, "Cannot add null criteria.");
if (this.criteria == null) {
this.criteria = criteria;
} else {
this.criteria.and(criteria);
}
return (T) this;
}
public Criteria getCriteria() {
return this.criteria;
}
}
@@ -1,73 +1,73 @@
/*
* Copyright 2013-2016 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.elasticsearch.core.query;
import org.elasticsearch.index.query.QueryBuilder;
/**
* DeleteQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class DeleteQuery {
private QueryBuilder query;
private String index;
private String type;
private Integer pageSize;
private Long scrollTimeInMillis;
public QueryBuilder getQuery() {
return query;
}
public void setQuery(QueryBuilder query) {
this.query = query;
}
public String getIndex() {
return index;
}
public void setIndex(String index) {
this.index = index;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Long getScrollTimeInMillis() {
return scrollTimeInMillis;
}
public void setScrollTimeInMillis(Long scrollTimeInMillis) {
this.scrollTimeInMillis = scrollTimeInMillis;
}
}
/*
* Copyright 2013-2016 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.elasticsearch.core.query;
import org.elasticsearch.index.query.QueryBuilder;
/**
* DeleteQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class DeleteQuery {
private QueryBuilder query;
private String index;
private String type;
private Integer pageSize;
private Long scrollTimeInMillis;
public QueryBuilder getQuery() {
return query;
}
public void setQuery(QueryBuilder query) {
this.query = query;
}
public String getIndex() {
return index;
}
public void setIndex(String index) {
this.index = index;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Long getScrollTimeInMillis() {
return scrollTimeInMillis;
}
public void setScrollTimeInMillis(Long scrollTimeInMillis) {
this.scrollTimeInMillis = scrollTimeInMillis;
}
}
@@ -1,32 +1,32 @@
/*
* Copyright 2013 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.elasticsearch.core.query;
/**
* Defines a Field that can be used within a Criteria.
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public interface Field {
/**
* Get the name of the field used in schema.xml of elasticsearch server
*
* @return
*/
String getName();
}
/*
* Copyright 2013 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.elasticsearch.core.query;
/**
* Defines a Field that can be used within a Criteria.
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public interface Field {
/**
* Get the name of the field used in schema.xml of elasticsearch server
*
* @return
*/
String getName();
}
@@ -1,35 +1,35 @@
/*
* Copyright 2013 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.elasticsearch.core.query;
/**
* GetQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class GetQuery {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
/*
* Copyright 2013 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.elasticsearch.core.query;
/**
* GetQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class GetQuery {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
@@ -1,90 +1,90 @@
/*
* Copyright 2013 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.elasticsearch.core.query;
/**
* IndexQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class IndexQuery {
private String id;
private Object object;
private Long version;
private String indexName;
private String type;
private String source;
private String parentId;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
public String getIndexName() {
return indexName;
}
public void setIndexName(String indexName) {
this.indexName = indexName;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
}
/*
* Copyright 2013 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.elasticsearch.core.query;
/**
* IndexQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class IndexQuery {
private String id;
private Object object;
private Long version;
private String indexName;
private String type;
private String source;
private String parentId;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
public String getIndexName() {
return indexName;
}
public void setIndexName(String indexName) {
this.indexName = indexName;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
}
@@ -1,187 +1,188 @@
/*
* Copyright 2013-2017 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.elasticsearch.core.query;
import static java.util.Collections.addAll;
import static org.springframework.data.elasticsearch.core.query.AbstractQuery.*;
import java.util.ArrayList;
import java.util.List;
import org.springframework.data.domain.Pageable;
/**
* MoreLikeThisQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class MoreLikeThisQuery {
private String id;
private String indexName;
private String type;
private List<String> searchIndices = new ArrayList<>();
private List<String> searchTypes = new ArrayList<>();
private List<String> fields = new ArrayList<>();
private String routing;
private Float percentTermsToMatch;
private Integer minTermFreq;
private Integer maxQueryTerms;
private List<String> stopWords = new ArrayList<>();
private Integer minDocFreq;
private Integer maxDocFreq;
private Integer minWordLen;
private Integer maxWordLen;
private Float boostTerms;
private Pageable pageable = DEFAULT_PAGE;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getIndexName() {
return indexName;
}
public void setIndexName(String indexName) {
this.indexName = indexName;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public List<String> getSearchIndices() {
return searchIndices;
}
public void addSearchIndices(String... searchIndices) {
addAll(this.searchIndices, searchIndices);
}
public List<String> getSearchTypes() {
return searchTypes;
}
public void addSearchTypes(String... searchTypes) {
addAll(this.searchTypes, searchTypes);
}
public List<String> getFields() {
return fields;
}
public void addFields(String... fields) {
addAll(this.fields, fields);
}
public String getRouting() {
return routing;
}
public void setRouting(String routing) {
this.routing = routing;
}
public Float getPercentTermsToMatch() {
return percentTermsToMatch;
}
public void setPercentTermsToMatch(Float percentTermsToMatch) {
this.percentTermsToMatch = percentTermsToMatch;
}
public Integer getMinTermFreq() {
return minTermFreq;
}
public void setMinTermFreq(Integer minTermFreq) {
this.minTermFreq = minTermFreq;
}
public Integer getMaxQueryTerms() {
return maxQueryTerms;
}
public void setMaxQueryTerms(Integer maxQueryTerms) {
this.maxQueryTerms = maxQueryTerms;
}
public List<String> getStopWords() {
return stopWords;
}
public void addStopWords(String... stopWords) {
addAll(this.stopWords, stopWords);
}
public Integer getMinDocFreq() {
return minDocFreq;
}
public void setMinDocFreq(Integer minDocFreq) {
this.minDocFreq = minDocFreq;
}
public Integer getMaxDocFreq() {
return maxDocFreq;
}
public void setMaxDocFreq(Integer maxDocFreq) {
this.maxDocFreq = maxDocFreq;
}
public Integer getMinWordLen() {
return minWordLen;
}
public void setMinWordLen(Integer minWordLen) {
this.minWordLen = minWordLen;
}
public Integer getMaxWordLen() {
return maxWordLen;
}
public void setMaxWordLen(Integer maxWordLen) {
this.maxWordLen = maxWordLen;
}
public Float getBoostTerms() {
return boostTerms;
}
public void setBoostTerms(Float boostTerms) {
this.boostTerms = boostTerms;
}
public Pageable getPageable() {
return pageable;
}
public void setPageable(Pageable pageable) {
this.pageable = pageable;
}
}
/*
* Copyright 2013-2016 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.elasticsearch.core.query;
import static java.util.Collections.addAll;
import static org.springframework.data.elasticsearch.core.query.AbstractQuery.*;
import java.util.ArrayList;
import java.util.List;
import org.springframework.data.domain.Pageable;
/**
* MoreLikeThisQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class MoreLikeThisQuery {
private String id;
private String indexName;
private String type;
private List<String> searchIndices = new ArrayList<String>();
private List<String> searchTypes = new ArrayList<String>();
private List<String> fields = new ArrayList<String>();
private String routing;
private Float percentTermsToMatch;
private Integer minTermFreq;
private Integer maxQueryTerms;
private List<String> stopWords = new ArrayList<String>();
private Integer minDocFreq;
private Integer maxDocFreq;
private Integer minWordLen;
private Integer maxWordLen;
private Float boostTerms;
private Pageable pageable = DEFAULT_PAGE;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getIndexName() {
return indexName;
}
public void setIndexName(String indexName) {
this.indexName = indexName;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public List<String> getSearchIndices() {
return searchIndices;
}
public void addSearchIndices(String... searchIndices) {
addAll(this.searchIndices, searchIndices);
}
public List<String> getSearchTypes() {
return searchTypes;
}
public void addSearchTypes(String... searchTypes) {
addAll(this.searchTypes, searchTypes);
}
public List<String> getFields() {
return fields;
}
public void addFields(String... fields) {
addAll(this.fields, fields);
}
public String getRouting() {
return routing;
}
public void setRouting(String routing) {
this.routing = routing;
}
public Float getPercentTermsToMatch() {
return percentTermsToMatch;
}
public void setPercentTermsToMatch(Float percentTermsToMatch) {
this.percentTermsToMatch = percentTermsToMatch;
}
public Integer getMinTermFreq() {
return minTermFreq;
}
public void setMinTermFreq(Integer minTermFreq) {
this.minTermFreq = minTermFreq;
}
public Integer getMaxQueryTerms() {
return maxQueryTerms;
}
public void setMaxQueryTerms(Integer maxQueryTerms) {
this.maxQueryTerms = maxQueryTerms;
}
public List<String> getStopWords() {
return stopWords;
}
public void addStopWords(String... stopWords) {
addAll(this.stopWords, stopWords);
}
public Integer getMinDocFreq() {
return minDocFreq;
}
public void setMinDocFreq(Integer minDocFreq) {
this.minDocFreq = minDocFreq;
}
public Integer getMaxDocFreq() {
return maxDocFreq;
}
public void setMaxDocFreq(Integer maxDocFreq) {
this.maxDocFreq = maxDocFreq;
}
public Integer getMinWordLen() {
return minWordLen;
}
public void setMinWordLen(Integer minWordLen) {
this.minWordLen = minWordLen;
}
public Integer getMaxWordLen() {
return maxWordLen;
}
public void setMaxWordLen(Integer maxWordLen) {
this.maxWordLen = maxWordLen;
}
public Float getBoostTerms() {
return boostTerms;
}
public void setBoostTerms(Float boostTerms) {
this.boostTerms = boostTerms;
}
public Pageable getPageable() {
return pageable;
}
public void setPageable(Pageable pageable) {
this.pageable = pageable;
}
}
@@ -1,156 +1,140 @@
/*
* Copyright 2013-2018 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.elasticsearch.core.query;
import java.util.ArrayList;
import java.util.List;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
import java.util.Arrays;
/**
* NativeSearchQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
* @author Jean-Baptiste Nizet
*/
public class NativeSearchQuery extends AbstractQuery implements SearchQuery {
private QueryBuilder query;
private QueryBuilder filter;
private List<SortBuilder> sorts;
private final List<ScriptField> scriptFields = new ArrayList<>();
private List<FacetRequest> facets;
private List<AbstractAggregationBuilder> aggregations;
private HighlightBuilder highlightBuilder;
private HighlightBuilder.Field[] highlightFields;
private List<IndexBoost> indicesBoost;
public NativeSearchQuery(QueryBuilder query) {
this.query = query;
}
public NativeSearchQuery(QueryBuilder query, QueryBuilder filter) {
this.query = query;
this.filter = filter;
}
public NativeSearchQuery(QueryBuilder query, QueryBuilder filter, List<SortBuilder> sorts) {
this.query = query;
this.filter = filter;
this.sorts = sorts;
}
public NativeSearchQuery(QueryBuilder query, QueryBuilder filter, List<SortBuilder> sorts, HighlightBuilder.Field[] highlightFields) {
this.query = query;
this.filter = filter;
this.sorts = sorts;
this.highlightFields = highlightFields;
}
public NativeSearchQuery(QueryBuilder query, QueryBuilder filter, List<SortBuilder> sorts,
HighlightBuilder highlighBuilder, HighlightBuilder.Field[] highlightFields) {
this.query = query;
this.filter = filter;
this.sorts = sorts;
this.highlightBuilder = highlighBuilder;
this.highlightFields = highlightFields;
}
public QueryBuilder getQuery() {
return query;
}
public QueryBuilder getFilter() {
return filter;
}
public List<SortBuilder> getElasticsearchSorts() {
return sorts;
}
@Override
public HighlightBuilder getHighlightBuilder() {
return highlightBuilder;
}
@Override
public HighlightBuilder.Field[] getHighlightFields() {
return highlightFields;
}
@Override
public List<ScriptField> getScriptFields() { return scriptFields; }
public void setScriptFields(List<ScriptField> scriptFields) {
this.scriptFields.addAll(scriptFields);
}
public void addScriptField(ScriptField... scriptField) {
scriptFields.addAll(Arrays.asList(scriptField));
}
public void addFacet(FacetRequest facetRequest) {
if (facets == null) {
facets = new ArrayList<>();
}
facets.add(facetRequest);
}
public void setFacets(List<FacetRequest> facets) {
this.facets = facets;
}
@Override
public List<FacetRequest> getFacets() {
return facets;
}
@Override
public List<AbstractAggregationBuilder> getAggregations() {
return aggregations;
}
public void addAggregation(AbstractAggregationBuilder aggregationBuilder) {
if (aggregations == null) {
aggregations = new ArrayList<>();
}
aggregations.add(aggregationBuilder);
}
public void setAggregations(List<AbstractAggregationBuilder> aggregations) {
this.aggregations = aggregations;
}
@Override
public List<IndexBoost> getIndicesBoost() {
return indicesBoost;
}
public void setIndicesBoost(List<IndexBoost> indicesBoost) {
this.indicesBoost = indicesBoost;
}
}
/*
* Copyright 2013-2016 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.elasticsearch.core.query;
import java.util.ArrayList;
import java.util.List;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
import java.util.Arrays;
/**
* NativeSearchQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
*/
public class NativeSearchQuery extends AbstractQuery implements SearchQuery {
private QueryBuilder query;
private QueryBuilder filter;
private List<SortBuilder> sorts;
private final List<ScriptField> scriptFields = new ArrayList<ScriptField>();
private List<FacetRequest> facets;
private List<AbstractAggregationBuilder> aggregations;
private HighlightBuilder.Field[] highlightFields;
private List<IndexBoost> indicesBoost;
public NativeSearchQuery(QueryBuilder query) {
this.query = query;
}
public NativeSearchQuery(QueryBuilder query, QueryBuilder filter) {
this.query = query;
this.filter = filter;
}
public NativeSearchQuery(QueryBuilder query, QueryBuilder filter, List<SortBuilder> sorts) {
this.query = query;
this.filter = filter;
this.sorts = sorts;
}
public NativeSearchQuery(QueryBuilder query, QueryBuilder filter, List<SortBuilder> sorts, HighlightBuilder.Field[] highlightFields) {
this.query = query;
this.filter = filter;
this.sorts = sorts;
this.highlightFields = highlightFields;
}
public QueryBuilder getQuery() {
return query;
}
public QueryBuilder getFilter() {
return filter;
}
public List<SortBuilder> getElasticsearchSorts() {
return sorts;
}
@Override
public HighlightBuilder.Field[] getHighlightFields() {
return highlightFields;
}
@Override
public List<ScriptField> getScriptFields() { return scriptFields; }
public void setScriptFields(List<ScriptField> scriptFields) {
this.scriptFields.addAll(scriptFields);
}
public void addScriptField(ScriptField... scriptField) {
scriptFields.addAll(Arrays.asList(scriptField));
}
public void addFacet(FacetRequest facetRequest) {
if (facets == null) {
facets = new ArrayList<FacetRequest>();
}
facets.add(facetRequest);
}
public void setFacets(List<FacetRequest> facets) {
this.facets = facets;
}
@Override
public List<FacetRequest> getFacets() {
return facets;
}
@Override
public List<AbstractAggregationBuilder> getAggregations() {
return aggregations;
}
public void addAggregation(AbstractAggregationBuilder aggregationBuilder) {
if (aggregations == null) {
aggregations = new ArrayList<AbstractAggregationBuilder>();
}
aggregations.add(aggregationBuilder);
}
public void setAggregations(List<AbstractAggregationBuilder> aggregations) {
this.aggregations = aggregations;
}
@Override
public List<IndexBoost> getIndicesBoost() {
return indicesBoost;
}
public void setIndicesBoost(List<IndexBoost> indicesBoost) {
this.indicesBoost = indicesBoost;
}
}
@@ -1,231 +1,199 @@
/*
* Copyright 2013-2018 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.elasticsearch.core.query;
import static org.springframework.util.CollectionUtils.isEmpty;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
/**
* NativeSearchQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
* @author Mark Paluch
* @author Alen Turkovic
* @author Sascha Woo
* @author Jean-Baptiste Nizet
*/
public class NativeSearchQueryBuilder {
private QueryBuilder queryBuilder;
private QueryBuilder filterBuilder;
private List<ScriptField> scriptFields = new ArrayList<>();
private List<SortBuilder> sortBuilders = new ArrayList<>();
private List<FacetRequest> facetRequests = new ArrayList<>();
private List<AbstractAggregationBuilder> aggregationBuilders = new ArrayList<>();
private HighlightBuilder highlightBuilder;
private HighlightBuilder.Field[] highlightFields;
private Pageable pageable = Pageable.unpaged();
private String[] indices;
private String[] types;
private String[] fields;
private SourceFilter sourceFilter;
private List<IndexBoost> indicesBoost;
private float minScore;
private boolean trackScores;
private Collection<String> ids;
private String route;
private SearchType searchType;
private IndicesOptions indicesOptions;
public NativeSearchQueryBuilder withQuery(QueryBuilder queryBuilder) {
this.queryBuilder = queryBuilder;
return this;
}
public NativeSearchQueryBuilder withFilter(QueryBuilder filterBuilder) {
this.filterBuilder = filterBuilder;
return this;
}
public NativeSearchQueryBuilder withSort(SortBuilder sortBuilder) {
this.sortBuilders.add(sortBuilder);
return this;
}
public NativeSearchQueryBuilder withScriptField(ScriptField scriptField) {
this.scriptFields.add(scriptField);
return this;
}
public NativeSearchQueryBuilder addAggregation(AbstractAggregationBuilder aggregationBuilder) {
this.aggregationBuilders.add(aggregationBuilder);
return this;
}
public NativeSearchQueryBuilder withFacet(FacetRequest facetRequest) {
facetRequests.add(facetRequest);
return this;
}
public NativeSearchQueryBuilder withHighlightBuilder(HighlightBuilder highlightBuilder) {
this.highlightBuilder = highlightBuilder;
return this;
}
public NativeSearchQueryBuilder withHighlightFields(HighlightBuilder.Field... highlightFields) {
this.highlightFields = highlightFields;
return this;
}
public NativeSearchQueryBuilder withIndicesBoost(List<IndexBoost> indicesBoost) {
this.indicesBoost = indicesBoost;
return this;
}
public NativeSearchQueryBuilder withPageable(Pageable pageable) {
this.pageable = pageable;
return this;
}
public NativeSearchQueryBuilder withIndices(String... indices) {
this.indices = indices;
return this;
}
public NativeSearchQueryBuilder withTypes(String... types) {
this.types = types;
return this;
}
public NativeSearchQueryBuilder withFields(String... fields) {
this.fields = fields;
return this;
}
public NativeSearchQueryBuilder withSourceFilter(SourceFilter sourceFilter) {
this.sourceFilter = sourceFilter;
return this;
}
public NativeSearchQueryBuilder withMinScore(float minScore) {
this.minScore = minScore;
return this;
}
/**
* @param trackScores whether to track scores.
* @return
* @since 3.1
*/
public NativeSearchQueryBuilder withTrackScores(boolean trackScores) {
this.trackScores = trackScores;
return this;
}
public NativeSearchQueryBuilder withIds(Collection<String> ids) {
this.ids = ids;
return this;
}
public NativeSearchQueryBuilder withRoute(String route) {
this.route = route;
return this;
}
public NativeSearchQueryBuilder withSearchType(SearchType searchType) {
this.searchType = searchType;
return this;
}
public NativeSearchQueryBuilder withIndicesOptions(IndicesOptions indicesOptions) {
this.indicesOptions = indicesOptions;
return this;
}
public NativeSearchQuery build() {
NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(queryBuilder, filterBuilder, sortBuilders,
highlightBuilder, highlightFields);
nativeSearchQuery.setPageable(pageable);
nativeSearchQuery.setTrackScores(trackScores);
if (indices != null) {
nativeSearchQuery.addIndices(indices);
}
if (types != null) {
nativeSearchQuery.addTypes(types);
}
if (fields != null) {
nativeSearchQuery.addFields(fields);
}
if (sourceFilter != null) {
nativeSearchQuery.addSourceFilter(sourceFilter);
}
if (indicesBoost != null) {
nativeSearchQuery.setIndicesBoost(indicesBoost);
}
if (!isEmpty(scriptFields)) {
nativeSearchQuery.setScriptFields(scriptFields);
}
if (!isEmpty(facetRequests)) {
nativeSearchQuery.setFacets(facetRequests);
}
if (!isEmpty(aggregationBuilders)) {
nativeSearchQuery.setAggregations(aggregationBuilders);
}
if (minScore > 0) {
nativeSearchQuery.setMinScore(minScore);
}
if (ids != null) {
nativeSearchQuery.setIds(ids);
}
if (route != null) {
nativeSearchQuery.setRoute(route);
}
if (searchType != null) {
nativeSearchQuery.setSearchType(searchType);
}
if (indicesOptions != null) {
nativeSearchQuery.setIndicesOptions(indicesOptions);
}
return nativeSearchQuery;
}
}
/*
* Copyright 2013-2016 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.elasticsearch.core.query;
import static org.springframework.util.CollectionUtils.isEmpty;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
/**
* NativeSearchQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
*/
public class NativeSearchQueryBuilder {
private QueryBuilder queryBuilder;
private QueryBuilder filterBuilder;
private List<ScriptField> scriptFields = new ArrayList<ScriptField>();
private List<SortBuilder> sortBuilders = new ArrayList<SortBuilder>();
private List<FacetRequest> facetRequests = new ArrayList<FacetRequest>();
private List<AbstractAggregationBuilder> aggregationBuilders = new ArrayList<AbstractAggregationBuilder>();
private HighlightBuilder.Field[] highlightFields;
private Pageable pageable;
private String[] indices;
private String[] types;
private String[] fields;
private SourceFilter sourceFilter;
private List<IndexBoost> indicesBoost;
private float minScore;
private Collection<String> ids;
private String route;
private SearchType searchType;
public NativeSearchQueryBuilder withQuery(QueryBuilder queryBuilder) {
this.queryBuilder = queryBuilder;
return this;
}
public NativeSearchQueryBuilder withFilter(QueryBuilder filterBuilder) {
this.filterBuilder = filterBuilder;
return this;
}
public NativeSearchQueryBuilder withSort(SortBuilder sortBuilder) {
this.sortBuilders.add(sortBuilder);
return this;
}
public NativeSearchQueryBuilder withScriptField(ScriptField scriptField) {
this.scriptFields.add(scriptField);
return this;
}
public NativeSearchQueryBuilder addAggregation(AbstractAggregationBuilder aggregationBuilder) {
this.aggregationBuilders.add(aggregationBuilder);
return this;
}
public NativeSearchQueryBuilder withFacet(FacetRequest facetRequest) {
facetRequests.add(facetRequest);
return this;
}
public NativeSearchQueryBuilder withHighlightFields(HighlightBuilder.Field... highlightFields) {
this.highlightFields = highlightFields;
return this;
}
public NativeSearchQueryBuilder withIndicesBoost(List<IndexBoost> indicesBoost) {
this.indicesBoost = indicesBoost;
return this;
}
public NativeSearchQueryBuilder withPageable(Pageable pageable) {
this.pageable = pageable;
return this;
}
public NativeSearchQueryBuilder withIndices(String... indices) {
this.indices = indices;
return this;
}
public NativeSearchQueryBuilder withTypes(String... types) {
this.types = types;
return this;
}
public NativeSearchQueryBuilder withFields(String... fields) {
this.fields = fields;
return this;
}
public NativeSearchQueryBuilder withSourceFilter(SourceFilter sourceFilter) {
this.sourceFilter = sourceFilter;
return this;
}
public NativeSearchQueryBuilder withMinScore(float minScore) {
this.minScore = minScore;
return this;
}
public NativeSearchQueryBuilder withIds(Collection<String> ids) {
this.ids = ids;
return this;
}
public NativeSearchQueryBuilder withRoute(String route) {
this.route = route;
return this;
}
public NativeSearchQueryBuilder withSearchType(SearchType searchType) {
this.searchType = searchType;
return this;
}
public NativeSearchQuery build() {
NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(queryBuilder, filterBuilder, sortBuilders, highlightFields);
if (pageable != null) {
nativeSearchQuery.setPageable(pageable);
}
if (indices != null) {
nativeSearchQuery.addIndices(indices);
}
if (types != null) {
nativeSearchQuery.addTypes(types);
}
if (fields != null) {
nativeSearchQuery.addFields(fields);
}
if (sourceFilter != null) {
nativeSearchQuery.addSourceFilter(sourceFilter);
}
if(indicesBoost != null) {
nativeSearchQuery.setIndicesBoost(indicesBoost);
}
if (!isEmpty(scriptFields)) {
nativeSearchQuery.setScriptFields(scriptFields);
}
if (!isEmpty(facetRequests)) {
nativeSearchQuery.setFacets(facetRequests);
}
if (!isEmpty(aggregationBuilders)) {
nativeSearchQuery.setAggregations(aggregationBuilders);
}
if (minScore > 0) {
nativeSearchQuery.setMinScore(minScore);
}
if (ids != null) {
nativeSearchQuery.setIds(ids);
}
if (route != null) {
nativeSearchQuery.setRoute(route);
}
if (searchType != null) {
nativeSearchQuery.setSearchType(searchType);
}
return nativeSearchQuery;
}
}
@@ -1,166 +1,157 @@
/*
* Copyright 2013-2018 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.elasticsearch.core.query;
import java.util.Collection;
import java.util.List;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.support.IndicesOptions;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
/**
* Query
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Mark Paluch
* @author Alen Turkovic
* @author Sascha Woo
*/
public interface Query {
int DEFAULT_PAGE_SIZE = 10;
Pageable DEFAULT_PAGE = PageRequest.of(0, DEFAULT_PAGE_SIZE);
/**
* restrict result to entries on given page. Corresponds to the 'start' and 'rows' parameter in elasticsearch
*
* @param pageable
* @return
*/
<T extends Query> T setPageable(Pageable pageable);
/**
* Get page settings if defined
*
* @return
*/
Pageable getPageable();
/**
* Add {@link org.springframework.data.domain.Sort} to query
*
* @param sort
* @return
*/
<T extends Query> T addSort(Sort sort);
/**
* @return null if not set
*/
Sort getSort();
/**
* Get Indices to be searched
*
* @return
*/
List<String> getIndices();
/**
* Add Indices to be added as part of search request
*
* @param indices
*/
void addIndices(String... indices);
/**
* Add types to be searched
*
* @param types
*/
void addTypes(String... types);
/**
* Get types to be searched
*
* @return
*/
List<String> getTypes();
/**
* Add fields to be added as part of search request
*
* @param fields
*/
void addFields(String... fields);
/**
* Get fields to be returned as part of search request
*
* @return
*/
List<String> getFields();
/**
* Add source filter to be added as part of search request
*
* @param sourceFilter
*/
void addSourceFilter(SourceFilter sourceFilter);
/**
* Get SourceFilter to be returned to get include and exclude source fields as part of search request.
*
* @return SourceFilter
*/
SourceFilter getSourceFilter();
/**
* Get minimum score
*
* @return
*/
float getMinScore();
/**
* Get if scores will be computed and tracked, regardless of whether sorting on a field. Defaults to <tt>false</tt>.
*
* @return
* @since 3.1
*/
boolean getTrackScores();
/**
* Get Ids
*
* @return
*/
Collection<String> getIds();
/**
* Get route
*
* @return
*/
String getRoute();
/**
* Type of search
*
* @return
*/
SearchType getSearchType();
/**
* Get indices options
*
* @return null if not set
*/
IndicesOptions getIndicesOptions();
}
/*
* Copyright 2013-2016 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.elasticsearch.core.query;
import java.util.Collection;
import java.util.List;
import org.elasticsearch.action.search.SearchType;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
/**
* Query
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public interface Query {
public static final int DEFAULT_PAGE_SIZE = 10;
public static final Pageable DEFAULT_PAGE = new PageRequest(0, DEFAULT_PAGE_SIZE);
/**
* restrict result to entries on given page. Corresponds to the 'start' and 'rows' parameter in elasticsearch
*
* @param pageable
* @return
*/
<T extends Query> T setPageable(Pageable pageable);
/**
* Get filter queries if defined
*
* @return
*/
// List<FilterQuery> getFilterQueries();
/**
* Get page settings if defined
*
* @return
*/
Pageable getPageable();
/**
* Add {@link org.springframework.data.domain.Sort} to query
*
* @param sort
* @return
*/
<T extends Query> T addSort(Sort sort);
/**
* @return null if not set
*/
Sort getSort();
/**
* Get Indices to be searched
*
* @return
*/
List<String> getIndices();
/**
* Add Indices to be added as part of search request
*
* @param indices
*/
void addIndices(String... indices);
/**
* Add types to be searched
*
* @param types
*/
void addTypes(String... types);
/**
* Get types to be searched
*
* @return
*/
List<String> getTypes();
/**
* Add fields to be added as part of search request
*
* @param fields
*/
void addFields(String... fields);
/**
* Get fields to be returned as part of search request
*
* @return
*/
List<String> getFields();
/**
* Add source filter to be added as part of search request
*
* @param sourceFilter
*/
void addSourceFilter(SourceFilter sourceFilter);
/**
* Get SourceFilter to be returned to get include and exclude source
* fields as part of search request.
*
* @return SourceFilter
*/
SourceFilter getSourceFilter();
/**
* Get minimum score
*
* @return
*/
float getMinScore();
/**
* Get Ids
*
* @return
*/
Collection<String> getIds();
/**
* Get route
*
* @return
*/
String getRoute();
/**
* Type of search
*
* @return
*/
SearchType getSearchType();
}
@@ -1,55 +1,52 @@
/*
* Copyright 2013-2018 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.elasticsearch.core.query;
import java.util.List;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
/**
* NativeSearchQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
* @author Jean-Baptiste Nizet
*/
public interface SearchQuery extends Query {
QueryBuilder getQuery();
QueryBuilder getFilter();
List<SortBuilder> getElasticsearchSorts();
@Deprecated
List<FacetRequest> getFacets();
List<AbstractAggregationBuilder> getAggregations();
HighlightBuilder getHighlightBuilder();
HighlightBuilder.Field[] getHighlightFields();
List<IndexBoost> getIndicesBoost();
List<ScriptField> getScriptFields();
}
/*
* Copyright 2013-2016 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.elasticsearch.core.query;
import java.util.List;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
/**
* NativeSearchQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
*/
public interface SearchQuery extends Query {
QueryBuilder getQuery();
QueryBuilder getFilter();
List<SortBuilder> getElasticsearchSorts();
@Deprecated
List<FacetRequest> getFacets();
List<AbstractAggregationBuilder> getAggregations();
HighlightBuilder.Field[] getHighlightFields();
List<IndexBoost> getIndicesBoost();
List<ScriptField> getScriptFields();
}
@@ -1,41 +1,41 @@
/*
* Copyright 2013 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.elasticsearch.core.query;
/**
* The most trivial implementation of a Field
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class SimpleField implements Field {
private final String name;
public SimpleField(String name) {
this.name = name;
}
@Override
public String getName() {
return this.name;
}
@Override
public String toString() {
return this.name;
}
/*
* Copyright 2013 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.elasticsearch.core.query;
/**
* The most trivial implementation of a Field
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class SimpleField implements Field {
private final String name;
public SimpleField(String name) {
this.name = name;
}
@Override
public String getName() {
return this.name;
}
@Override
public String toString() {
return this.name;
}
}
@@ -1,49 +1,49 @@
/*
* Copyright 2013 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.elasticsearch.core.query;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
/**
* StringQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class StringQuery extends AbstractQuery {
private String source;
public StringQuery(String source) {
this.source = source;
}
public StringQuery(String source, Pageable pageable) {
this.source = source;
this.pageable = pageable;
}
public StringQuery(String source, Pageable pageable, Sort sort) {
this.pageable = pageable;
this.sort = sort;
this.source = source;
}
public String getSource() {
return source;
}
}
/*
* Copyright 2013 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.elasticsearch.core.query;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
/**
* StringQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class StringQuery extends AbstractQuery {
private String source;
public StringQuery(String source) {
this.source = source;
}
public StringQuery(String source, Pageable pageable) {
this.source = source;
this.pageable = pageable;
}
public StringQuery(String source, Pageable pageable, Sort sort) {
this.pageable = pageable;
this.sort = sort;
this.source = source;
}
public String getSource() {
return source;
}
}
@@ -1,33 +1,33 @@
/*
* Copyright 2013-2014 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.elasticsearch.repository;
import java.io.Serializable;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
/**
* @param <T>
* @param <ID>
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Oliver Gierke
*/
@NoRepositoryBean
public interface ElasticsearchCrudRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {
}
/*
* Copyright 2013-2014 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.elasticsearch.repository;
import java.io.Serializable;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
/**
* @param <T>
* @param <ID>
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Oliver Gierke
*/
@NoRepositoryBean
public interface ElasticsearchCrudRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {
}
@@ -1,48 +1,48 @@
/*
* Copyright 2013-2016 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.elasticsearch.repository;
import java.io.Serializable;
import org.elasticsearch.index.query.QueryBuilder;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.data.repository.NoRepositoryBean;
/**
* @param <T>
* @param <ID>
* @author Rizwan Idrees
* @author Mohsin Husen
*/
@NoRepositoryBean
public interface ElasticsearchRepository<T, ID extends Serializable> extends ElasticsearchCrudRepository<T, ID> {
<S extends T> S index(S entity);
Iterable<T> search(QueryBuilder query);
Page<T> search(QueryBuilder query, Pageable pageable);
Page<T> search(SearchQuery searchQuery);
Page<T> searchSimilar(T entity, String[] fields, Pageable pageable);
void refresh();
Class<T> getEntityClass();
}
/*
* Copyright 2013-2016 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.elasticsearch.repository;
import java.io.Serializable;
import org.elasticsearch.index.query.QueryBuilder;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.data.repository.NoRepositoryBean;
/**
* @param <T>
* @param <ID>
* @author Rizwan Idrees
* @author Mohsin Husen
*/
@NoRepositoryBean
public interface ElasticsearchRepository<T, ID extends Serializable> extends ElasticsearchCrudRepository<T, ID> {
<S extends T> S index(S entity);
Iterable<T> search(QueryBuilder query);
Page<T> search(QueryBuilder query, Pageable pageable);
Page<T> search(SearchQuery searchQuery);
Page<T> searchSimilar(T entity, String[] fields, Pageable pageable);
void refresh();
Class<T> getEntityClass();
}
@@ -1,84 +1,71 @@
/*
* Copyright 2013-2018 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.elasticsearch.repository.cdi;
import java.lang.annotation.Annotation;
import java.util.Optional;
import java.util.Set;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.repository.support.ElasticsearchRepositoryFactory;
import org.springframework.data.repository.cdi.CdiRepositoryBean;
import org.springframework.data.repository.config.CustomRepositoryImplementationDetector;
import org.springframework.util.Assert;
/**
* Uses {@link CdiRepositoryBean} to create
* {@link org.springframework.data.elasticsearch.repository.ElasticsearchRepository} instances.
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Mark Paluch
*/
public class ElasticsearchRepositoryBean<T> extends CdiRepositoryBean<T> {
private final Bean<ElasticsearchOperations> elasticsearchOperationsBean;
/**
* Creates a new {@link ElasticsearchRepositoryBean}.
*
* @param operations must not be {@literal null}.
* @param qualifiers must not be {@literal null}.
* @param repositoryType must not be {@literal null}.
* @param beanManager must not be {@literal null}.
* @param detector detector for the custom {@link org.springframework.data.repository.Repository} implementations
* {@link CustomRepositoryImplementationDetector}, can be {@literal null}.
*/
public ElasticsearchRepositoryBean(Bean<ElasticsearchOperations> operations, Set<Annotation> qualifiers,
Class<T> repositoryType, BeanManager beanManager, CustomRepositoryImplementationDetector detector) {
super(qualifiers, repositoryType, beanManager, Optional.of(detector));
Assert.notNull(operations, "Cannot create repository with 'null' for ElasticsearchOperations.");
this.elasticsearchOperationsBean = operations;
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.cdi.CdiRepositoryBean#create(javax.enterprise.context.spi.CreationalContext, java.lang.Class)
*/
@Override
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType) {
ElasticsearchOperations operations = getDependencyInstance(elasticsearchOperationsBean,
ElasticsearchOperations.class);
return create(() -> new ElasticsearchRepositoryFactory(operations), repositoryType);
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.cdi.CdiRepositoryBean#getScope()
*/
@Override
public Class<? extends Annotation> getScope() {
return elasticsearchOperationsBean.getScope();
}
}
/*
* Copyright 2013-2014 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.elasticsearch.repository.cdi;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import java.lang.annotation.Annotation;
import java.util.Set;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.repository.support.ElasticsearchRepositoryFactory;
import org.springframework.data.repository.cdi.CdiRepositoryBean;
import org.springframework.data.repository.config.CustomRepositoryImplementationDetector;
import org.springframework.util.Assert;
/**
* Uses CdiRepositoryBean to create ElasticsearchRepository instances.
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Mark Paluch
*/
public class ElasticsearchRepositoryBean<T> extends CdiRepositoryBean<T> {
private final Bean<ElasticsearchOperations> elasticsearchOperationsBean;
/**
* Creates a new {@link ElasticsearchRepositoryBean}.
*
* @param operations must not be {@literal null}.
* @param qualifiers must not be {@literal null}.
* @param repositoryType must not be {@literal null}.
* @param beanManager must not be {@literal null}.
* @param detector detector for the custom {@link org.springframework.data.repository.Repository} implementations
* {@link CustomRepositoryImplementationDetector}, can be {@literal null}.
*/
public ElasticsearchRepositoryBean(Bean<ElasticsearchOperations> operations, Set<Annotation> qualifiers,
Class<T> repositoryType, BeanManager beanManager, CustomRepositoryImplementationDetector detector) {
super(qualifiers, repositoryType, beanManager, detector);
Assert.notNull(operations, "Cannot create repository with 'null' for ElasticsearchOperations.");
this.elasticsearchOperationsBean = operations;
}
@Override
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType, Object customImplementation) {
ElasticsearchOperations elasticsearchOperations = getDependencyInstance(elasticsearchOperationsBean,
ElasticsearchOperations.class);
return new ElasticsearchRepositoryFactory(elasticsearchOperations).getRepository(repositoryType,
customImplementation);
}
@Override
public Class<? extends Annotation> getScope() {
return elasticsearchOperationsBean.getScope();
}
}
@@ -1,83 +1,82 @@
/*
* Copyright 2013-2017 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.elasticsearch.repository.cdi;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.UnsatisfiedResolutionException;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.ProcessBean;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.repository.cdi.CdiRepositoryBean;
import org.springframework.data.repository.cdi.CdiRepositoryExtensionSupport;
/**
* CDI extension to export Elasticsearch repositories.
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Oliver Gierke
* @author Mark Paluch
*/
public class ElasticsearchRepositoryExtension extends CdiRepositoryExtensionSupport {
private final Map<Set<Annotation>, Bean<ElasticsearchOperations>> elasticsearchOperationsMap = new HashMap<>();
@SuppressWarnings("unchecked")
<T> void processBean(@Observes ProcessBean<T> processBean) {
Bean<T> bean = processBean.getBean();
for (Type type : bean.getTypes()) {
if (type instanceof Class<?> && ElasticsearchOperations.class.isAssignableFrom((Class<?>) type)) {
elasticsearchOperationsMap.put(bean.getQualifiers(), ((Bean<ElasticsearchOperations>) bean));
}
}
}
void afterBeanDiscovery(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager) {
for (Entry<Class<?>, Set<Annotation>> entry : getRepositoryTypes()) {
Class<?> repositoryType = entry.getKey();
Set<Annotation> qualifiers = entry.getValue();
CdiRepositoryBean<?> repositoryBean = createRepositoryBean(repositoryType, qualifiers, beanManager);
afterBeanDiscovery.addBean(repositoryBean);
registerBean(repositoryBean);
}
}
private <T> CdiRepositoryBean<T> createRepositoryBean(Class<T> repositoryType, Set<Annotation> qualifiers,
BeanManager beanManager) {
if (!this.elasticsearchOperationsMap.containsKey(qualifiers)) {
throw new UnsatisfiedResolutionException(String.format("Unable to resolve a bean for '%s' with qualifiers %s.",
ElasticsearchOperations.class.getName(), qualifiers));
}
Bean<ElasticsearchOperations> elasticsearchOperationsBean = this.elasticsearchOperationsMap.get(qualifiers);
return new ElasticsearchRepositoryBean<>(elasticsearchOperationsBean, qualifiers, repositoryType, beanManager,
getCustomImplementationDetector());
}
}
/*
* Copyright 2013-2016 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.elasticsearch.repository.cdi;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.UnsatisfiedResolutionException;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.ProcessBean;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.repository.cdi.CdiRepositoryBean;
import org.springframework.data.repository.cdi.CdiRepositoryExtensionSupport;
/**
* CDI extension to export Elasticsearch repositories.
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Oliver Gierke
* @author Mark Paluch
*/
public class ElasticsearchRepositoryExtension extends CdiRepositoryExtensionSupport {
private final Map<Set<Annotation>, Bean<ElasticsearchOperations>> elasticsearchOperationsMap = new HashMap<Set<Annotation>, Bean<ElasticsearchOperations>>();
@SuppressWarnings("unchecked")
<T> void processBean(@Observes ProcessBean<T> processBean) {
Bean<T> bean = processBean.getBean();
for (Type type : bean.getTypes()) {
if (type instanceof Class<?> && ElasticsearchOperations.class.isAssignableFrom((Class<?>) type)) {
elasticsearchOperationsMap.put(bean.getQualifiers(), ((Bean<ElasticsearchOperations>) bean));
}
}
}
void afterBeanDiscovery(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager) {
for (Entry<Class<?>, Set<Annotation>> entry : getRepositoryTypes()) {
Class<?> repositoryType = entry.getKey();
Set<Annotation> qualifiers = entry.getValue();
CdiRepositoryBean<?> repositoryBean = createRepositoryBean(repositoryType, qualifiers, beanManager);
afterBeanDiscovery.addBean(repositoryBean);
registerBean(repositoryBean);
}
}
private <T> CdiRepositoryBean<T> createRepositoryBean(Class<T> repositoryType, Set<Annotation> qualifiers,
BeanManager beanManager) {
Bean<ElasticsearchOperations> elasticsearchOperationsBean = this.elasticsearchOperationsMap.get(qualifiers);
if (elasticsearchOperationsBean == null) {
throw new UnsatisfiedResolutionException(String.format("Unable to resolve a bean for '%s' with qualifiers %s.",
ElasticsearchOperations.class.getName(), qualifiers));
}
return new ElasticsearchRepositoryBean<T>(elasticsearchOperationsBean, qualifiers, repositoryType, beanManager,
getCustomImplementationDetector());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2017 the original author or authors.
* Copyright 2013 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.
@@ -38,16 +38,15 @@ import org.w3c.dom.Element;
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Mark Paluch
*/
public class ElasticsearchRepositoryConfigExtension extends RepositoryConfigurationExtensionSupport {
/*
* (non-Javadoc)
* @see org.springframework.data.repository.config.RepositoryConfigurationExtension#getRepositoryFactoryBeanClassName()
* @see org.springframework.data.repository.config.RepositoryConfigurationExtension#getRepositoryFactoryClassName()
*/
@Override
public String getRepositoryFactoryBeanClassName() {
public String getRepositoryFactoryClassName() {
return ElasticsearchRepositoryFactoryBean.class.getName();
}
@@ -60,7 +59,7 @@ public class ElasticsearchRepositoryConfigExtension extends RepositoryConfigurat
return "elasticsearch";
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#postProcess(org.springframework.beans.factory.support.BeanDefinitionBuilder, org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource)
*/
@@ -71,7 +70,7 @@ public class ElasticsearchRepositoryConfigExtension extends RepositoryConfigurat
builder.addPropertyReference("elasticsearchOperations", attributes.getString("elasticsearchTemplateRef"));
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#postProcess(org.springframework.beans.factory.support.BeanDefinitionBuilder, org.springframework.data.repository.config.XmlRepositoryConfigurationSource)
*/
@@ -88,7 +87,7 @@ public class ElasticsearchRepositoryConfigExtension extends RepositoryConfigurat
*/
@Override
protected Collection<Class<? extends Annotation>> getIdentifyingAnnotations() {
return Collections.<Class<? extends Annotation>> singleton(Document.class);
return Collections.<Class<? extends Annotation>>singleton(Document.class);
}
/*
@@ -97,6 +96,6 @@ public class ElasticsearchRepositoryConfigExtension extends RepositoryConfigurat
*/
@Override
protected Collection<Class<?>> getIdentifyingTypes() {
return Arrays.<Class<?>> asList(ElasticsearchRepository.class, ElasticsearchCrudRepository.class);
return Arrays.<Class<?>>asList(ElasticsearchRepository.class, ElasticsearchCrudRepository.class);
}
}
@@ -48,7 +48,7 @@ public @interface EnableElasticsearchRepositories {
/**
* Base packages to scan for annotated components. {@link #value()} is an alias for (and mutually exclusive with) this
* attribute. Use {@link #basePackageClasses()} for a type-safe alternative to text-based package names.
* attribute. Use {@link #basePackageClasses()} for a type-safe alternative to String-based package names.
*/
String[] basePackages() default {};
@@ -1,44 +1,44 @@
/*
* Copyright 2013 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.elasticsearch.repository.query;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.repository.query.QueryMethod;
import org.springframework.data.repository.query.RepositoryQuery;
/**
* AbstractElasticsearchRepositoryQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public abstract class AbstractElasticsearchRepositoryQuery implements RepositoryQuery {
protected ElasticsearchQueryMethod queryMethod;
protected ElasticsearchOperations elasticsearchOperations;
public AbstractElasticsearchRepositoryQuery(ElasticsearchQueryMethod queryMethod,
ElasticsearchOperations elasticsearchOperations) {
this.queryMethod = queryMethod;
this.elasticsearchOperations = elasticsearchOperations;
}
@Override
public QueryMethod getQueryMethod() {
return queryMethod;
}
}
/*
* Copyright 2013 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.elasticsearch.repository.query;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.repository.query.QueryMethod;
import org.springframework.data.repository.query.RepositoryQuery;
/**
* AbstractElasticsearchRepositoryQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public abstract class AbstractElasticsearchRepositoryQuery implements RepositoryQuery {
protected ElasticsearchQueryMethod queryMethod;
protected ElasticsearchOperations elasticsearchOperations;
public AbstractElasticsearchRepositoryQuery(ElasticsearchQueryMethod queryMethod,
ElasticsearchOperations elasticsearchOperations) {
this.queryMethod = queryMethod;
this.elasticsearchOperations = elasticsearchOperations;
}
@Override
public QueryMethod getQueryMethod() {
return queryMethod;
}
}
@@ -1,107 +1,104 @@
/*
* Copyright 2013-2017 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.elasticsearch.repository.query;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.data.elasticsearch.repository.query.parser.ElasticsearchQueryCreator;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.repository.query.ParametersParameterAccessor;
import org.springframework.data.repository.query.parser.PartTree;
import org.springframework.util.ClassUtils;
import org.springframework.data.util.CloseableIterator;
import org.springframework.data.util.StreamUtils;
/**
* ElasticsearchPartQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Kevin Leturc
* @author Mark Paluch
*/
public class ElasticsearchPartQuery extends AbstractElasticsearchRepositoryQuery {
private final PartTree tree;
private final MappingContext<?, ElasticsearchPersistentProperty> mappingContext;
public ElasticsearchPartQuery(ElasticsearchQueryMethod method, ElasticsearchOperations elasticsearchOperations) {
super(method, elasticsearchOperations);
this.tree = new PartTree(method.getName(), method.getEntityInformation().getJavaType());
this.mappingContext = elasticsearchOperations.getElasticsearchConverter().getMappingContext();
}
@Override
public Object execute(Object[] parameters) {
ParametersParameterAccessor accessor = new ParametersParameterAccessor(queryMethod.getParameters(), parameters);
CriteriaQuery query = createQuery(accessor);
if(tree.isDelete()) {
Object result = countOrGetDocumentsForDelete(query, accessor);
elasticsearchOperations.delete(query, queryMethod.getEntityInformation().getJavaType());
return result;
} else if (queryMethod.isPageQuery()) {
query.setPageable(accessor.getPageable());
return elasticsearchOperations.queryForPage(query, queryMethod.getEntityInformation().getJavaType());
} else if (queryMethod.isStreamQuery()) {
Class<?> entityType = queryMethod.getEntityInformation().getJavaType();
if (query.getPageable().isUnpaged()) {
int itemCount = (int) elasticsearchOperations.count(query, queryMethod.getEntityInformation().getJavaType());
query.setPageable(PageRequest.of(0, Math.max(1, itemCount)));
}
return StreamUtils.createStreamFromIterator((CloseableIterator<Object>) elasticsearchOperations.stream(query, entityType));
} else if (queryMethod.isCollectionQuery()) {
if (accessor.getPageable() == null) {
int itemCount = (int) elasticsearchOperations.count(query, queryMethod.getEntityInformation().getJavaType());
query.setPageable(PageRequest.of(0, Math.max(1, itemCount)));
} else {
query.setPageable(accessor.getPageable());
}
return elasticsearchOperations.queryForList(query, queryMethod.getEntityInformation().getJavaType());
} else if (tree.isCountProjection()) {
return elasticsearchOperations.count(query, queryMethod.getEntityInformation().getJavaType());
}
return elasticsearchOperations.queryForObject(query, queryMethod.getEntityInformation().getJavaType());
}
private Object countOrGetDocumentsForDelete(CriteriaQuery query, ParametersParameterAccessor accessor) {
Object result = null;
if (queryMethod.isCollectionQuery()) {
if (accessor.getPageable().isUnpaged()) {
int itemCount = (int) elasticsearchOperations.count(query, queryMethod.getEntityInformation().getJavaType());
query.setPageable(PageRequest.of(0, Math.max(1, itemCount)));
} else {
query.setPageable(accessor.getPageable());
}
result = elasticsearchOperations.queryForList(query, queryMethod.getEntityInformation().getJavaType());
}
if (ClassUtils.isAssignable(Number.class, queryMethod.getReturnedObjectType())) {
result = elasticsearchOperations.count(query, queryMethod.getEntityInformation().getJavaType());
}
return result;
}
public CriteriaQuery createQuery(ParametersParameterAccessor accessor) {
return new ElasticsearchQueryCreator(tree, accessor, mappingContext).createQuery();
}
}
/*
* Copyright 2013 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.elasticsearch.repository.query;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.data.elasticsearch.repository.query.parser.ElasticsearchQueryCreator;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.repository.query.ParametersParameterAccessor;
import org.springframework.data.repository.query.parser.PartTree;
import org.springframework.util.ClassUtils;
import org.springframework.data.util.CloseableIterator;
import org.springframework.data.util.StreamUtils;
/**
* ElasticsearchPartQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Kevin Leturc
*/
public class ElasticsearchPartQuery extends AbstractElasticsearchRepositoryQuery {
private final PartTree tree;
private final MappingContext<?, ElasticsearchPersistentProperty> mappingContext;
public ElasticsearchPartQuery(ElasticsearchQueryMethod method, ElasticsearchOperations elasticsearchOperations) {
super(method, elasticsearchOperations);
this.tree = new PartTree(method.getName(), method.getEntityInformation().getJavaType());
this.mappingContext = elasticsearchOperations.getElasticsearchConverter().getMappingContext();
}
@Override
public Object execute(Object[] parameters) {
ParametersParameterAccessor accessor = new ParametersParameterAccessor(queryMethod.getParameters(), parameters);
CriteriaQuery query = createQuery(accessor);
if(tree.isDelete()) {
Object result = countOrGetDocumentsForDelete(query, accessor);
elasticsearchOperations.delete(query, queryMethod.getEntityInformation().getJavaType());
return result;
} else if (queryMethod.isPageQuery()) {
query.setPageable(accessor.getPageable());
return elasticsearchOperations.queryForPage(query, queryMethod.getEntityInformation().getJavaType());
} else if (queryMethod.isStreamQuery()) {
Class<?> entityType = queryMethod.getEntityInformation().getJavaType();
if (query.getPageable() == null) {
query.setPageable(new PageRequest(0, 20));
}
return StreamUtils.createStreamFromIterator((CloseableIterator<Object>) elasticsearchOperations.stream(query, entityType));
} else if (queryMethod.isCollectionQuery()) {
if (accessor.getPageable() == null) {
int itemCount = (int) elasticsearchOperations.count(query, queryMethod.getEntityInformation().getJavaType());
query.setPageable(new PageRequest(0, Math.max(1, itemCount)));
} else {
query.setPageable(accessor.getPageable());
}
return elasticsearchOperations.queryForList(query, queryMethod.getEntityInformation().getJavaType());
} else if (tree.isCountProjection()) {
return elasticsearchOperations.count(query, queryMethod.getEntityInformation().getJavaType());
}
return elasticsearchOperations.queryForObject(query, queryMethod.getEntityInformation().getJavaType());
}
private Object countOrGetDocumentsForDelete(CriteriaQuery query, ParametersParameterAccessor accessor) {
Object result = null;
if (queryMethod.isCollectionQuery()) {
if (accessor.getPageable() == null) {
int itemCount = (int) elasticsearchOperations.count(query, queryMethod.getEntityInformation().getJavaType());
query.setPageable(new PageRequest(0, Math.max(1, itemCount)));
} else {
query.setPageable(accessor.getPageable());
}
result = elasticsearchOperations.queryForList(query, queryMethod.getEntityInformation().getJavaType());
}
if (ClassUtils.isAssignable(Number.class, queryMethod.getReturnedObjectType())) {
result = elasticsearchOperations.count(query, queryMethod.getEntityInformation().getJavaType());
}
return result;
}
public CriteriaQuery createQuery(ParametersParameterAccessor accessor) {
return new ElasticsearchQueryCreator(tree, accessor, mappingContext).createQuery();
}
}
@@ -1,50 +1,51 @@
/*
* Copyright 2013-2017 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.elasticsearch.repository.query;
import java.lang.reflect.Method;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.elasticsearch.annotations.Query;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.query.QueryMethod;
/**
* ElasticsearchQueryMethod
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Oliver Gierke
* @author Mark Paluch
*/
public class ElasticsearchQueryMethod extends QueryMethod {
private final Query queryAnnotation;
public ElasticsearchQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory) {
super(method, metadata, factory);
this.queryAnnotation = method.getAnnotation(Query.class);
}
public boolean hasAnnotatedQuery() {
return this.queryAnnotation != null;
}
public String getAnnotatedQuery() {
return (String) AnnotationUtils.getValue(queryAnnotation, "value");
}
}
/*
* Copyright 2013-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.elasticsearch.repository.query;
import java.lang.reflect.Method;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.elasticsearch.annotations.Query;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.query.QueryMethod;
import org.springframework.util.StringUtils;
/**
* ElasticsearchQueryMethod
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Oliver Gierke
*/
public class ElasticsearchQueryMethod extends QueryMethod {
private final Query queryAnnotation;
public ElasticsearchQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory) {
super(method, metadata, factory);
this.queryAnnotation = method.getAnnotation(Query.class);
}
public boolean hasAnnotatedQuery() {
return this.queryAnnotation != null;
}
public String getAnnotatedQuery() {
String query = (String) AnnotationUtils.getValue(queryAnnotation, "value");
return StringUtils.hasText(query) ? query : null;
}
}
@@ -1,105 +1,103 @@
/*
* Copyright 2013-2017 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.elasticsearch.repository.query;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.convert.DateTimeConverters;
import org.springframework.data.elasticsearch.core.query.StringQuery;
import org.springframework.data.repository.query.ParametersParameterAccessor;
import org.springframework.util.Assert;
/**
* ElasticsearchStringQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Mark Paluch
*/
public class ElasticsearchStringQuery extends AbstractElasticsearchRepositoryQuery {
private static final Pattern PARAMETER_PLACEHOLDER = Pattern.compile("\\?(\\d+)");
private String query;
private final GenericConversionService conversionService = new GenericConversionService();
{
if (!conversionService.canConvert(java.util.Date.class, String.class)) {
conversionService.addConverter(DateTimeConverters.JavaDateConverter.INSTANCE);
}
if (!conversionService.canConvert(org.joda.time.ReadableInstant.class, String.class)) {
conversionService.addConverter(DateTimeConverters.JodaDateTimeConverter.INSTANCE);
}
if (!conversionService.canConvert(org.joda.time.LocalDateTime.class, String.class)) {
conversionService.addConverter(DateTimeConverters.JodaLocalDateTimeConverter.INSTANCE);
}
}
public ElasticsearchStringQuery(ElasticsearchQueryMethod queryMethod, ElasticsearchOperations elasticsearchOperations,
String query) {
super(queryMethod, elasticsearchOperations);
Assert.notNull(query, "Query cannot be empty");
this.query = query;
}
@Override
public Object execute(Object[] parameters) {
ParametersParameterAccessor accessor = new ParametersParameterAccessor(queryMethod.getParameters(), parameters);
StringQuery stringQuery = createQuery(accessor);
if (queryMethod.isPageQuery()) {
stringQuery.setPageable(accessor.getPageable());
return elasticsearchOperations.queryForPage(stringQuery, queryMethod.getEntityInformation().getJavaType());
} else if (queryMethod.isCollectionQuery()) {
if (accessor.getPageable().isPaged()) {
stringQuery.setPageable(accessor.getPageable());
}
return elasticsearchOperations.queryForList(stringQuery, queryMethod.getEntityInformation().getJavaType());
}
return elasticsearchOperations.queryForObject(stringQuery, queryMethod.getEntityInformation().getJavaType());
}
protected StringQuery createQuery(ParametersParameterAccessor parameterAccessor) {
String queryString = replacePlaceholders(this.query, parameterAccessor);
return new StringQuery(queryString);
}
private String replacePlaceholders(String input, ParametersParameterAccessor accessor) {
Matcher matcher = PARAMETER_PLACEHOLDER.matcher(input);
String result = input;
while (matcher.find()) {
String group = matcher.group();
int index = Integer.parseInt(matcher.group(1));
result = result.replace(group, getParameterWithIndex(accessor, index));
}
return result;
}
private String getParameterWithIndex(ParametersParameterAccessor accessor, int index) {
Object parameter = accessor.getBindableValue(index);
if (parameter == null) {
return "null";
}
if (conversionService.canConvert(parameter.getClass(), String.class)) {
return conversionService.convert(parameter, String.class);
}
return parameter.toString();
}
}
/*
* Copyright 2013 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.elasticsearch.repository.query;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.convert.DateTimeConverters;
import org.springframework.data.elasticsearch.core.query.StringQuery;
import org.springframework.data.repository.query.ParametersParameterAccessor;
import org.springframework.util.Assert;
/**
* ElasticsearchStringQuery
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class ElasticsearchStringQuery extends AbstractElasticsearchRepositoryQuery {
private static final Pattern PARAMETER_PLACEHOLDER = Pattern.compile("\\?(\\d+)");
private String query;
private final GenericConversionService conversionService = new GenericConversionService();
{
if (!conversionService.canConvert(java.util.Date.class, String.class)) {
conversionService.addConverter(DateTimeConverters.JavaDateConverter.INSTANCE);
}
if (!conversionService.canConvert(org.joda.time.ReadableInstant.class, String.class)) {
conversionService.addConverter(DateTimeConverters.JodaDateTimeConverter.INSTANCE);
}
if (!conversionService.canConvert(org.joda.time.LocalDateTime.class, String.class)) {
conversionService.addConverter(DateTimeConverters.JodaLocalDateTimeConverter.INSTANCE);
}
}
public ElasticsearchStringQuery(ElasticsearchQueryMethod queryMethod,
ElasticsearchOperations elasticsearchOperations, String query) {
super(queryMethod, elasticsearchOperations);
Assert.notNull(query, "Query cannot be empty");
this.query = query;
}
@Override
public Object execute(Object[] parameters) {
ParametersParameterAccessor accessor = new ParametersParameterAccessor(queryMethod.getParameters(), parameters);
StringQuery stringQuery = createQuery(accessor);
if (queryMethod.isPageQuery()) {
stringQuery.setPageable(accessor.getPageable());
return elasticsearchOperations.queryForPage(stringQuery, queryMethod.getEntityInformation().getJavaType());
} else if (queryMethod.isCollectionQuery()) {
if (accessor.getPageable() != null) {
stringQuery.setPageable(accessor.getPageable());
}
return elasticsearchOperations.queryForList(stringQuery, queryMethod.getEntityInformation().getJavaType());
}
return elasticsearchOperations.queryForObject(stringQuery, queryMethod.getEntityInformation().getJavaType());
}
protected StringQuery createQuery(ParametersParameterAccessor parameterAccessor) {
String queryString = replacePlaceholders(this.query, parameterAccessor);
return new StringQuery(queryString);
}
private String replacePlaceholders(String input, ParametersParameterAccessor accessor) {
Matcher matcher = PARAMETER_PLACEHOLDER.matcher(input);
String result = input;
while (matcher.find()) {
String group = matcher.group();
int index = Integer.parseInt(matcher.group(1));
result = result.replace(group, getParameterWithIndex(accessor, index));
}
return result;
}
private String getParameterWithIndex(ParametersParameterAccessor accessor, int index) {
Object parameter = accessor.getBindableValue(index);
if (parameter == null) {
return "null";
}
if (conversionService.canConvert(parameter.getClass(), String.class)) {
return conversionService.convert(parameter, String.class);
}
return parameter.toString();
}
}
@@ -1,195 +1,195 @@
/*
* Copyright 2013 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.elasticsearch.repository.query.parser;
import java.util.Collection;
import java.util.Iterator;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.geo.GeoBox;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.data.geo.Box;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Point;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.repository.query.ParameterAccessor;
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
import org.springframework.data.repository.query.parser.Part;
import org.springframework.data.repository.query.parser.PartTree;
/**
* ElasticsearchQueryCreator
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Franck Marchand
* @author Artur Konczak
*/
public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuery, CriteriaQuery> {
private final MappingContext<?, ElasticsearchPersistentProperty> context;
public ElasticsearchQueryCreator(PartTree tree, ParameterAccessor parameters,
MappingContext<?, ElasticsearchPersistentProperty> context) {
super(tree, parameters);
this.context = context;
}
public ElasticsearchQueryCreator(PartTree tree, MappingContext<?, ElasticsearchPersistentProperty> context) {
super(tree);
this.context = context;
}
@Override
protected CriteriaQuery create(Part part, Iterator<Object> iterator) {
PersistentPropertyPath<ElasticsearchPersistentProperty> path = context
.getPersistentPropertyPath(part.getProperty());
return new CriteriaQuery(from(part,
new Criteria(path.toDotPath(ElasticsearchPersistentProperty.PropertyToFieldNameConverter.INSTANCE)), iterator));
}
@Override
protected CriteriaQuery and(Part part, CriteriaQuery base, Iterator<Object> iterator) {
if (base == null) {
return create(part, iterator);
}
PersistentPropertyPath<ElasticsearchPersistentProperty> path = context
.getPersistentPropertyPath(part.getProperty());
return base.addCriteria(from(part,
new Criteria(path.toDotPath(ElasticsearchPersistentProperty.PropertyToFieldNameConverter.INSTANCE)), iterator));
}
@Override
protected CriteriaQuery or(CriteriaQuery base, CriteriaQuery query) {
return new CriteriaQuery(base.getCriteria().or(query.getCriteria()));
}
@Override
protected CriteriaQuery complete(CriteriaQuery query, Sort sort) {
if (query == null) {
return null;
}
return query.addSort(sort);
}
private Criteria from(Part part, Criteria instance, Iterator<?> parameters) {
Part.Type type = part.getType();
Criteria criteria = instance;
if (criteria == null) {
criteria = new Criteria();
}
switch (type) {
case TRUE:
return criteria.is(true);
case FALSE:
return criteria.is(false);
case NEGATING_SIMPLE_PROPERTY:
return criteria.is(parameters.next()).not();
case REGEX:
return criteria.expression(parameters.next().toString());
case LIKE:
case STARTING_WITH:
return criteria.startsWith(parameters.next().toString());
case ENDING_WITH:
return criteria.endsWith(parameters.next().toString());
case CONTAINING:
return criteria.contains(parameters.next().toString());
case GREATER_THAN:
return criteria.greaterThan(parameters.next());
case AFTER:
case GREATER_THAN_EQUAL:
return criteria.greaterThanEqual(parameters.next());
case LESS_THAN:
return criteria.lessThan(parameters.next());
case BEFORE:
case LESS_THAN_EQUAL:
return criteria.lessThanEqual(parameters.next());
case BETWEEN:
return criteria.between(parameters.next(), parameters.next());
case IN:
return criteria.in(asArray(parameters.next()));
case NOT_IN:
return criteria.notIn(asArray(parameters.next()));
case SIMPLE_PROPERTY:
case WITHIN: {
Object firstParameter = parameters.next();
Object secondParameter = null;
if (type == Part.Type.SIMPLE_PROPERTY) {
if (part.getProperty().getType() != GeoPoint.class)
return criteria.is(firstParameter);
else {
// it means it's a simple find with exact geopoint matching (e.g. findByLocation)
// and because Elasticsearch does not have any kind of query with just a geopoint
// as argument we use a "geo distance" query with a distance of one meter.
secondParameter = ".001km";
}
} else {
secondParameter = parameters.next();
}
if (firstParameter instanceof GeoPoint && secondParameter instanceof String)
return criteria.within((GeoPoint) firstParameter, (String) secondParameter);
if (firstParameter instanceof Point && secondParameter instanceof Distance)
return criteria.within((Point) firstParameter, (Distance) secondParameter);
if (firstParameter instanceof String && secondParameter instanceof String)
return criteria.within((String) firstParameter, (String) secondParameter);
}
case NEAR: {
Object firstParameter = parameters.next();
if (firstParameter instanceof GeoBox) {
return criteria.boundedBy((GeoBox) firstParameter);
}
if (firstParameter instanceof Box) {
return criteria.boundedBy(GeoBox.fromBox((Box) firstParameter));
}
Object secondParameter = parameters.next();
// "near" query can be the same query as the "within" query
if (firstParameter instanceof GeoPoint && secondParameter instanceof String)
return criteria.within((GeoPoint) firstParameter, (String) secondParameter);
if (firstParameter instanceof Point && secondParameter instanceof Distance)
return criteria.within((Point) firstParameter, (Distance) secondParameter);
if (firstParameter instanceof String && secondParameter instanceof String)
return criteria.within((String) firstParameter, (String) secondParameter);
}
default:
throw new InvalidDataAccessApiUsageException("Illegal criteria found '" + type + "'.");
}
}
private Object[] asArray(Object o) {
if (o instanceof Collection) {
return ((Collection<?>) o).toArray();
} else if (o.getClass().isArray()) {
return (Object[]) o;
}
return new Object[]{o};
}
}
/*
* Copyright 2013 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.elasticsearch.repository.query.parser;
import java.util.Collection;
import java.util.Iterator;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.geo.GeoBox;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.data.geo.Box;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Point;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.context.PersistentPropertyPath;
import org.springframework.data.repository.query.ParameterAccessor;
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
import org.springframework.data.repository.query.parser.Part;
import org.springframework.data.repository.query.parser.PartTree;
/**
* ElasticsearchQueryCreator
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Franck Marchand
* @author Artur Konczak
*/
public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuery, CriteriaQuery> {
private final MappingContext<?, ElasticsearchPersistentProperty> context;
public ElasticsearchQueryCreator(PartTree tree, ParameterAccessor parameters,
MappingContext<?, ElasticsearchPersistentProperty> context) {
super(tree, parameters);
this.context = context;
}
public ElasticsearchQueryCreator(PartTree tree, MappingContext<?, ElasticsearchPersistentProperty> context) {
super(tree);
this.context = context;
}
@Override
protected CriteriaQuery create(Part part, Iterator<Object> iterator) {
PersistentPropertyPath<ElasticsearchPersistentProperty> path = context
.getPersistentPropertyPath(part.getProperty());
return new CriteriaQuery(from(part,
new Criteria(path.toDotPath(ElasticsearchPersistentProperty.PropertyToFieldNameConverter.INSTANCE)), iterator));
}
@Override
protected CriteriaQuery and(Part part, CriteriaQuery base, Iterator<Object> iterator) {
if (base == null) {
return create(part, iterator);
}
PersistentPropertyPath<ElasticsearchPersistentProperty> path = context
.getPersistentPropertyPath(part.getProperty());
return base.addCriteria(from(part,
new Criteria(path.toDotPath(ElasticsearchPersistentProperty.PropertyToFieldNameConverter.INSTANCE)), iterator));
}
@Override
protected CriteriaQuery or(CriteriaQuery base, CriteriaQuery query) {
return new CriteriaQuery(base.getCriteria().or(query.getCriteria()));
}
@Override
protected CriteriaQuery complete(CriteriaQuery query, Sort sort) {
if (query == null) {
return null;
}
return query.addSort(sort);
}
private Criteria from(Part part, Criteria instance, Iterator<?> parameters) {
Part.Type type = part.getType();
Criteria criteria = instance;
if (criteria == null) {
criteria = new Criteria();
}
switch (type) {
case TRUE:
return criteria.is(true);
case FALSE:
return criteria.is(false);
case NEGATING_SIMPLE_PROPERTY:
return criteria.is(parameters.next()).not();
case REGEX:
return criteria.expression(parameters.next().toString());
case LIKE:
case STARTING_WITH:
return criteria.startsWith(parameters.next().toString());
case ENDING_WITH:
return criteria.endsWith(parameters.next().toString());
case CONTAINING:
return criteria.contains(parameters.next().toString());
case GREATER_THAN:
return criteria.greaterThan(parameters.next());
case AFTER:
case GREATER_THAN_EQUAL:
return criteria.greaterThanEqual(parameters.next());
case LESS_THAN:
return criteria.lessThan(parameters.next());
case BEFORE:
case LESS_THAN_EQUAL:
return criteria.lessThanEqual(parameters.next());
case BETWEEN:
return criteria.between(parameters.next(), parameters.next());
case IN:
return criteria.in(asArray(parameters.next()));
case NOT_IN:
return criteria.notIn(asArray(parameters.next()));
case SIMPLE_PROPERTY:
case WITHIN: {
Object firstParameter = parameters.next();
Object secondParameter = null;
if (type == Part.Type.SIMPLE_PROPERTY) {
if (part.getProperty().getType() != GeoPoint.class)
return criteria.is(firstParameter);
else {
// it means it's a simple find with exact geopoint matching (e.g. findByLocation)
// and because Elasticsearch does not have any kind of query with just a geopoint
// as argument we use a "geo distance" query with a distance of one meter.
secondParameter = ".001km";
}
} else {
secondParameter = parameters.next();
}
if (firstParameter instanceof GeoPoint && secondParameter instanceof String)
return criteria.within((GeoPoint) firstParameter, (String) secondParameter);
if (firstParameter instanceof Point && secondParameter instanceof Distance)
return criteria.within((Point) firstParameter, (Distance) secondParameter);
if (firstParameter instanceof String && secondParameter instanceof String)
return criteria.within((String) firstParameter, (String) secondParameter);
}
case NEAR: {
Object firstParameter = parameters.next();
if (firstParameter instanceof GeoBox) {
return criteria.boundedBy((GeoBox) firstParameter);
}
if (firstParameter instanceof Box) {
return criteria.boundedBy(GeoBox.fromBox((Box) firstParameter));
}
Object secondParameter = parameters.next();
// "near" query can be the same query as the "within" query
if (firstParameter instanceof GeoPoint && secondParameter instanceof String)
return criteria.within((GeoPoint) firstParameter, (String) secondParameter);
if (firstParameter instanceof Point && secondParameter instanceof Distance)
return criteria.within((Point) firstParameter, (Distance) secondParameter);
if (firstParameter instanceof String && secondParameter instanceof String)
return criteria.within((String) firstParameter, (String) secondParameter);
}
default:
throw new InvalidDataAccessApiUsageException("Illegal criteria found '" + type + "'.");
}
}
private Object[] asArray(Object o) {
if (o instanceof Collection) {
return ((Collection<?>) o).toArray();
} else if (o.getClass().isArray()) {
return (Object[]) o;
}
return new Object[]{o};
}
}
@@ -23,25 +23,15 @@ import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.index.query.QueryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.*;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.query.DeleteQuery;
import org.springframework.data.elasticsearch.core.query.GetQuery;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.MoreLikeThisQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.util.Assert;
@@ -54,32 +44,31 @@ import org.springframework.util.Assert;
* @author Ryan Henszey
* @author Kevin Leturc
* @author Mark Paluch
* @author Christoph Strobl
* @author Michael Wirth
*/
public abstract class AbstractElasticsearchRepository<T, ID extends Serializable>
implements ElasticsearchRepository<T, ID> {
public abstract class AbstractElasticsearchRepository<T, ID extends Serializable> implements
ElasticsearchRepository<T, ID> {
static final Logger LOGGER = LoggerFactory.getLogger(AbstractElasticsearchRepository.class);
protected ElasticsearchOperations elasticsearchOperations;
protected Class<T> entityClass;
protected ElasticsearchEntityInformation<T, ID> entityInformation;
public AbstractElasticsearchRepository() {}
public AbstractElasticsearchRepository() {
}
public AbstractElasticsearchRepository(ElasticsearchOperations elasticsearchOperations) {
Assert.notNull(elasticsearchOperations, "ElasticsearchOperations must not be null!");
this.setElasticsearchOperations(elasticsearchOperations);
}
public AbstractElasticsearchRepository(ElasticsearchEntityInformation<T, ID> metadata,
ElasticsearchOperations elasticsearchOperations) {
ElasticsearchOperations elasticsearchOperations) {
this(elasticsearchOperations);
Assert.notNull(metadata, "ElasticsearchEntityInformation must not be null!");
this.entityInformation = metadata;
setEntityClass(this.entityInformation.getJavaType());
try {
@@ -105,19 +94,19 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
}
@Override
public Optional<T> findById(ID id) {
public T findOne(ID id) {
GetQuery query = new GetQuery();
query.setId(stringIdRepresentation(id));
return Optional.ofNullable(elasticsearchOperations.queryForObject(query, getEntityClass()));
return elasticsearchOperations.queryForObject(query, getEntityClass());
}
@Override
public Iterable<T> findAll() {
int itemCount = (int) this.count();
if (itemCount == 0) {
return new PageImpl<>(Collections.<T> emptyList());
return new PageImpl<T>(Collections.<T>emptyList());
}
return this.findAll(PageRequest.of(0, Math.max(1, itemCount)));
return this.findAll(new PageRequest(0, Math.max(1, itemCount)));
}
@Override
@@ -130,17 +119,19 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
public Iterable<T> findAll(Sort sort) {
int itemCount = (int) this.count();
if (itemCount == 0) {
return new PageImpl<>(Collections.<T> emptyList());
return new PageImpl<T>(Collections.<T>emptyList());
}
SearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
.withPageable(PageRequest.of(0, itemCount, sort)).build();
.withPageable(new PageRequest(0, itemCount, sort)).build();
return elasticsearchOperations.queryForPage(query, getEntityClass());
}
@Override
public Iterable<T> findAllById(Iterable<ID> ids) {
public Iterable<T> findAll(Iterable<ID> ids) {
Assert.notNull(ids, "ids can't be null.");
SearchQuery query = new NativeSearchQueryBuilder().withIds(stringIdsRepresentation(ids)).build();
SearchQuery query = new NativeSearchQueryBuilder()
.withIds(stringIdsRepresentation(ids))
.build();
return elasticsearchOperations.multiGet(query, getEntityClass());
}
@@ -161,7 +152,7 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
public <S extends T> List<S> save(List<S> entities) {
Assert.notNull(entities, "Cannot insert 'null' as a List.");
Assert.notEmpty(entities, "Cannot insert empty List.");
List<IndexQuery> queries = new ArrayList<>();
List<IndexQuery> queries = new ArrayList<IndexQuery>();
for (S s : entities) {
queries.add(createIndexQuery(s));
}
@@ -176,9 +167,9 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
}
@Override
public <S extends T> Iterable<S> saveAll(Iterable<S> entities) {
public <S extends T> Iterable<S> save(Iterable<S> entities) {
Assert.notNull(entities, "Cannot insert 'null' as a List.");
List<IndexQuery> queries = new ArrayList<>();
List<IndexQuery> queries = new ArrayList<IndexQuery>();
for (S s : entities) {
queries.add(createIndexQuery(s));
}
@@ -188,8 +179,8 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
}
@Override
public boolean existsById(ID id) {
return findById(id).isPresent();
public boolean exists(ID id) {
return findOne(id) != null;
}
@Override
@@ -197,9 +188,9 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(query).build();
int count = (int) elasticsearchOperations.count(searchQuery, getEntityClass());
if (count == 0) {
return new PageImpl<>(Collections.<T> emptyList());
return new PageImpl<T>(Collections.<T>emptyList());
}
searchQuery.setPageable(PageRequest.of(0, count));
searchQuery.setPageable(new PageRequest(0, count));
return elasticsearchOperations.queryForPage(searchQuery, getEntityClass());
}
@@ -228,7 +219,7 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
}
@Override
public void deleteById(ID id) {
public void delete(ID id) {
Assert.notNull(id, "Cannot delete entity with id 'null'.");
elasticsearchOperations.delete(entityInformation.getIndexName(), entityInformation.getType(),
stringIdRepresentation(id));
@@ -238,12 +229,12 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
@Override
public void delete(T entity) {
Assert.notNull(entity, "Cannot delete 'null' entity.");
deleteById(extractIdFromBean(entity));
delete(extractIdFromBean(entity));
elasticsearchOperations.refresh(entityInformation.getIndexName());
}
@Override
public void deleteAll(Iterable<? extends T> entities) {
public void delete(Iterable<? extends T> entities) {
Assert.notNull(entities, "Cannot delete 'null' list.");
for (T entity : entities) {
delete(entity);
@@ -317,12 +308,15 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
}
protected ID extractIdFromBean(T entity) {
return entityInformation.getId(entity);
if (entityInformation != null) {
return entityInformation.getId(entity);
}
return null;
}
private List<String> stringIdsRepresentation(Iterable<ID> ids) {
Assert.notNull(ids, "ids can't be null.");
List<String> stringIds = new ArrayList<>();
List<String> stringIds = new ArrayList<String>();
for (ID id : ids) {
stringIds.add(stringIdRepresentation(id));
}
@@ -332,10 +326,16 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
protected abstract String stringIdRepresentation(ID id);
private Long extractVersionFromBean(T entity) {
return entityInformation.getVersion(entity);
if (entityInformation != null) {
return entityInformation.getVersion(entity);
}
return null;
}
private String extractParentIdFromBean(T entity) {
return entityInformation.getParentId(entity);
if (entityInformation != null) {
return entityInformation.getParentId(entity);
}
return null;
}
}
@@ -1,38 +1,39 @@
/*
* Copyright 2013-2017 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.elasticsearch.repository.support;
import org.springframework.data.repository.core.EntityInformation;
/**
* @param <T>
* @param <ID>
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Christoph Strobl
*/
public interface ElasticsearchEntityInformation<T, ID> extends EntityInformation<T, ID> {
String getIdAttribute();
String getIndexName();
String getType();
Long getVersion(T entity);
String getParentId(T entity);
}
/*
* Copyright 2013 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.elasticsearch.repository.support;
import java.io.Serializable;
import org.springframework.data.repository.core.EntityInformation;
/**
* @param <T>
* @param <ID>
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public interface ElasticsearchEntityInformation<T, ID extends Serializable> extends EntityInformation<T, ID> {
String getIdAttribute();
String getIndexName();
String getType();
Long getVersion(T entity);
String getParentId(T entity);
}
@@ -1,28 +1,29 @@
/*
* Copyright 2013-2017 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.elasticsearch.repository.support;
/**
* ElasticsearchEntityInformationCreator
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Christoph Strobl
*/
public interface ElasticsearchEntityInformationCreator {
<T, ID> ElasticsearchEntityInformation<T, ID> getEntityInformation(Class<T> domainClass);
}
/*
* Copyright 2013 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.elasticsearch.repository.support;
import java.io.Serializable;
/**
* ElasticsearchEntityInformationCreator
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public interface ElasticsearchEntityInformationCreator {
<T, ID extends Serializable> ElasticsearchEntityInformation<T, ID> getEntityInformation(Class<T> domainClass);
}
@@ -1,56 +1,57 @@
/*
* Copyright 2013-2017 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.elasticsearch.repository.support;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.util.Assert;
/**
* ElasticsearchEntityInformationCreatorImpl
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Oliver Gierke
* @author Mark Paluch
* @author Christoph Strobl
*/
public class ElasticsearchEntityInformationCreatorImpl implements ElasticsearchEntityInformationCreator {
private final MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext;
public ElasticsearchEntityInformationCreatorImpl(
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext) {
Assert.notNull(mappingContext, "MappingContext must not be null!");
this.mappingContext = mappingContext;
}
@Override
@SuppressWarnings("unchecked")
public <T, ID> ElasticsearchEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
ElasticsearchPersistentEntity<T> persistentEntity = (ElasticsearchPersistentEntity<T>) mappingContext
.getRequiredPersistentEntity(domainClass);
Assert.notNull(persistentEntity, String.format("Unable to obtain mapping metadata for %s!", domainClass));
Assert.notNull(persistentEntity.getIdProperty(), String.format("No id property found for %s!", domainClass));
return new MappingElasticsearchEntityInformation<>(persistentEntity);
}
}
/*
* Copyright 2013-2017 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.elasticsearch.repository.support;
import java.io.Serializable;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.util.Assert;
/**
* ElasticsearchEntityInformationCreatorImpl
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Oliver Gierke
* @author Mark Paluch
*/
public class ElasticsearchEntityInformationCreatorImpl implements ElasticsearchEntityInformationCreator {
private final MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext;
public ElasticsearchEntityInformationCreatorImpl(
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext) {
Assert.notNull(mappingContext, "MappingContext must not be null!");
this.mappingContext = mappingContext;
}
@Override
@SuppressWarnings("unchecked")
public <T, ID extends Serializable> ElasticsearchEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
ElasticsearchPersistentEntity<T> persistentEntity = (ElasticsearchPersistentEntity<T>) mappingContext
.getPersistentEntity(domainClass);
Assert.notNull(persistentEntity, String.format("Unable to obtain mapping metadata for %s!", domainClass));
Assert.notNull(persistentEntity.getIdProperty(), String.format("No id property found for %s!", domainClass));
return new MappingElasticsearchEntityInformation<T, ID>(persistentEntity);
}
}
@@ -15,10 +15,10 @@
*/
package org.springframework.data.elasticsearch.repository.support;
import static org.springframework.data.querydsl.QuerydslUtils.*;
import static org.springframework.data.querydsl.QueryDslUtils.*;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Optional;
import java.util.UUID;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
@@ -27,16 +27,13 @@ import org.springframework.data.elasticsearch.repository.query.ElasticsearchPart
import org.springframework.data.elasticsearch.repository.query.ElasticsearchQueryMethod;
import org.springframework.data.elasticsearch.repository.query.ElasticsearchStringQuery;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
import org.springframework.data.repository.core.NamedQueries;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
import org.springframework.data.repository.query.QueryLookupStrategy;
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.data.spel.EvaluationContextProvider;
import org.springframework.util.Assert;
/**
@@ -47,7 +44,6 @@ import org.springframework.util.Assert;
* @author Ryan Henszey
* @author Gad Akuka
* @author Mark Paluch
* @author Christoph Strobl
*/
public class ElasticsearchRepositoryFactory extends RepositoryFactorySupport {
@@ -55,24 +51,23 @@ public class ElasticsearchRepositoryFactory extends RepositoryFactorySupport {
private final ElasticsearchEntityInformationCreator entityInformationCreator;
public ElasticsearchRepositoryFactory(ElasticsearchOperations elasticsearchOperations) {
Assert.notNull(elasticsearchOperations, "ElasticsearchOperations must not be null!");
this.elasticsearchOperations = elasticsearchOperations;
this.entityInformationCreator = new ElasticsearchEntityInformationCreatorImpl(
elasticsearchOperations.getElasticsearchConverter().getMappingContext());
this.entityInformationCreator = new ElasticsearchEntityInformationCreatorImpl(elasticsearchOperations
.getElasticsearchConverter().getMappingContext());
}
@Override
public <T, ID> ElasticsearchEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
public <T, ID extends Serializable> ElasticsearchEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
return entityInformationCreator.getEntityInformation(domainClass);
}
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
@SuppressWarnings({"rawtypes", "unchecked"})
protected Object getTargetRepository(RepositoryInformation metadata) {
return getTargetRepositoryViaReflection(metadata, getEntityInformation(metadata.getDomainType()),
elasticsearchOperations);
return getTargetRepositoryViaReflection(metadata,getEntityInformation(metadata.getDomainType()), elasticsearchOperations);
}
@Override
@@ -80,7 +75,8 @@ public class ElasticsearchRepositoryFactory extends RepositoryFactorySupport {
if (isQueryDslRepository(metadata.getRepositoryInterface())) {
throw new IllegalArgumentException("QueryDsl Support has not been implemented yet.");
}
if (Integer.class.isAssignableFrom(metadata.getIdType()) || Long.class.isAssignableFrom(metadata.getIdType())
if (Integer.class.isAssignableFrom(metadata.getIdType())
|| Long.class.isAssignableFrom(metadata.getIdType())
|| Double.class.isAssignableFrom(metadata.getIdType())) {
return NumberKeyedRepository.class;
} else if (metadata.getIdType() == String.class) {
@@ -93,18 +89,17 @@ public class ElasticsearchRepositoryFactory extends RepositoryFactorySupport {
}
private static boolean isQueryDslRepository(Class<?> repositoryInterface) {
return QUERY_DSL_PRESENT && QuerydslPredicateExecutor.class.isAssignableFrom(repositoryInterface);
return QUERY_DSL_PRESENT && QueryDslPredicateExecutor.class.isAssignableFrom(repositoryInterface);
}
@Override
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(Key key,
QueryMethodEvaluationContextProvider evaluationContextProvider) {
return Optional.of(new ElasticsearchQueryLookupStrategy());
protected QueryLookupStrategy getQueryLookupStrategy(QueryLookupStrategy.Key key) {
return new ElasticsearchQueryLookupStrategy();
}
private class ElasticsearchQueryLookupStrategy implements QueryLookupStrategy {
/*
/*
* (non-Javadoc)
* @see org.springframework.data.repository.query.QueryLookupStrategy#resolveQuery(java.lang.reflect.Method, org.springframework.data.repository.core.RepositoryMetadata, org.springframework.data.projection.ProjectionFactory, org.springframework.data.repository.core.NamedQueries)
*/
@@ -1,94 +1,101 @@
/*
* Copyright 2013-2017 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.elasticsearch.repository.support;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.repository.core.support.PersistentEntityInformation;
import org.springframework.util.Assert;
/**
* Elasticsearch specific implementation of
* {@link org.springframework.data.repository.core.support.AbstractEntityInformation}
*
* @param <T>
* @param <ID>
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Ryan Henszey
* @author Oliver Gierke
* @author Mark Paluch
* @author Christoph Strobl
*/
public class MappingElasticsearchEntityInformation<T, ID> extends PersistentEntityInformation<T, ID>
implements ElasticsearchEntityInformation<T, ID> {
private final ElasticsearchPersistentEntity<T> entityMetadata;
private final String indexName;
private final String type;
public MappingElasticsearchEntityInformation(ElasticsearchPersistentEntity<T> entity) {
this(entity, entity.getIndexName(), entity.getIndexType());
}
public MappingElasticsearchEntityInformation(ElasticsearchPersistentEntity<T> entity, String indexName, String type) {
super(entity);
Assert.notNull(indexName, "IndexName must not be null!");
Assert.notNull(type, "IndexType must not be null!");
this.entityMetadata = entity;
this.indexName = indexName;
this.type = type;
}
@Override
public String getIdAttribute() {
return entityMetadata.getRequiredIdProperty().getFieldName();
}
@Override
public String getIndexName() {
return indexName;
}
@Override
public String getType() {
return type;
}
@Override
public Long getVersion(T entity) {
ElasticsearchPersistentProperty versionProperty = entityMetadata.getVersionProperty();
try {
return versionProperty != null ? (Long) entityMetadata.getPropertyAccessor(entity).getProperty(versionProperty) : null;
} catch (Exception e) {
throw new IllegalStateException("failed to load version field", e);
}
}
@Override
public String getParentId(T entity) {
ElasticsearchPersistentProperty parentProperty = entityMetadata.getParentIdProperty();
try {
return parentProperty != null ? (String) entityMetadata.getPropertyAccessor(entity).getProperty(parentProperty) : null;
} catch (Exception e) {
throw new IllegalStateException("failed to load parent ID: " + e, e);
}
}
}
/*
* Copyright 2013-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.elasticsearch.repository.support;
import java.io.Serializable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.repository.core.support.PersistentEntityInformation;
import org.springframework.util.Assert;
/**
* Elasticsearch specific implementation of
* {@link org.springframework.data.repository.core.support.AbstractEntityInformation}
*
* @param <T>
* @param <ID>
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Ryan Henszey
* @author Oliver Gierke
*/
public class MappingElasticsearchEntityInformation<T, ID extends Serializable> extends PersistentEntityInformation<T, ID>
implements ElasticsearchEntityInformation<T, ID> {
private static final Logger logger = LoggerFactory.getLogger(MappingElasticsearchEntityInformation.class);
private final ElasticsearchPersistentEntity<T> entityMetadata;
private final String indexName;
private final String type;
public MappingElasticsearchEntityInformation(ElasticsearchPersistentEntity<T> entity) {
this(entity, null, null);
}
public MappingElasticsearchEntityInformation(ElasticsearchPersistentEntity<T> entity, String indexName, String type) {
super(entity);
this.entityMetadata = entity;
this.indexName = indexName;
this.type = type;
}
@Override
public String getIdAttribute() {
Assert.notNull(entityMetadata.getIdProperty(), "Unable to identify 'id' property in class "
+ entityMetadata.getType().getSimpleName()
+ ". Make sure the 'id' property is annotated with @Id or named as 'id' or 'documentId' ");
return entityMetadata.getIdProperty().getFieldName();
}
@Override
public String getIndexName() {
return indexName != null ? indexName : entityMetadata.getIndexName();
}
@Override
public String getType() {
return type != null ? type : entityMetadata.getIndexType();
}
@Override
public Long getVersion(T entity) {
ElasticsearchPersistentProperty versionProperty = entityMetadata.getVersionProperty();
try {
if (versionProperty != null) {
return (Long) entityMetadata.getPropertyAccessor(entity).getProperty(versionProperty);
}
} catch (Exception e) {
throw new IllegalStateException("failed to load version field", e);
}
return null;
}
@Override
public String getParentId(T entity) {
ElasticsearchPersistentProperty parentProperty = entityMetadata.getParentIdProperty();
try {
if (parentProperty != null) {
return (String) entityMetadata.getPropertyAccessor(entity).getProperty(parentProperty);
}
} catch (Exception e) {
throw new IllegalStateException("failed to load parent ID: " + e, e);
}
return null;
}
}
@@ -1,47 +1,47 @@
/*
* Copyright 2013 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.elasticsearch.repository.support;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
/**
* Elasticsearch specific repository implementation. Likely to be used as target within
* {@link ElasticsearchRepositoryFactory}
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Ryan Henszey
*/
public class SimpleElasticsearchRepository<T> extends AbstractElasticsearchRepository<T, String> {
public SimpleElasticsearchRepository() {
super();
}
public SimpleElasticsearchRepository(ElasticsearchEntityInformation<T, String> metadata,
ElasticsearchOperations elasticsearchOperations) {
super(metadata, elasticsearchOperations);
}
public SimpleElasticsearchRepository(ElasticsearchOperations elasticsearchOperations) {
super(elasticsearchOperations);
}
@Override
protected String stringIdRepresentation(String id) {
return id;
}
}
/*
* Copyright 2013 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.elasticsearch.repository.support;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
/**
* Elasticsearch specific repository implementation. Likely to be used as target within
* {@link ElasticsearchRepositoryFactory}
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Ryan Henszey
*/
public class SimpleElasticsearchRepository<T> extends AbstractElasticsearchRepository<T, String> {
public SimpleElasticsearchRepository() {
super();
}
public SimpleElasticsearchRepository(ElasticsearchEntityInformation<T, String> metadata,
ElasticsearchOperations elasticsearchOperations) {
super(metadata, elasticsearchOperations);
}
public SimpleElasticsearchRepository(ElasticsearchOperations elasticsearchOperations) {
super(elasticsearchOperations);
}
@Override
protected String stringIdRepresentation(String id) {
return id;
}
}
-284
View File
@@ -1,290 +1,6 @@
Spring Data Elasticsearch Changelog
===================================
Changes in version 3.1.3.RELEASE (2018-11-27)
---------------------------------------------
* DATAES-503 - Missing copy_to property in @Field Annotation.
* DATAES-496 - Release 3.1.3 (Lovelace SR3).
* DATAES-492 - Missing normalizer property in @Field and @InnerField Annotation.
* DATAES-445 - Usage example of scan and scroll is misleading.
Changes in version 3.0.12.RELEASE (2018-11-27)
----------------------------------------------
* DATAES-503 - Missing copy_to property in @Field Annotation.
* DATAES-492 - Missing normalizer property in @Field and @InnerField Annotation.
* DATAES-490 - Release 3.0.12 (Kay SR12).
* DATAES-445 - Usage example of scan and scroll is misleading.
Changes in version 2.1.17.RELEASE (2018-11-27)
----------------------------------------------
* DATAES-491 - Release 2.1.17 (Ingalls SR17).
Changes in version 3.1.2.RELEASE (2018-10-29)
---------------------------------------------
* DATAES-489 - Release 3.1.2 (Lovelace SR2).
Changes in version 2.1.16.RELEASE (2018-10-15)
----------------------------------------------
* DATAES-484 - Release 2.1.16 (Ingalls SR16).
Changes in version 3.0.11.RELEASE (2018-10-15)
----------------------------------------------
* DATAES-485 - Release 3.0.11 (Kay SR11).
Changes in version 3.1.1.RELEASE (2018-10-15)
---------------------------------------------
* DATAES-486 - Release 3.1.1 (Lovelace SR1).
Changes in version 3.1.0.RELEASE (2018-09-21)
---------------------------------------------
* DATAES-480 - Release 3.1 GA (Lovelace).
* DATAES-479 - NativeSearchQueryBuilder should have a withHighlighter() method.
Changes in version 3.0.10.RELEASE (2018-09-10)
----------------------------------------------
* DATAES-473 - Release 3.0.10 (Kay SR10).
Changes in version 2.1.15.RELEASE (2018-09-10)
----------------------------------------------
* DATAES-474 - Release 2.1.15 (Ingalls SR15).
Changes in version 3.1.0.RC2 (2018-08-20)
-----------------------------------------
* DATAES-472 - Release 3.1 RC2 (Lovelace).
Changes in version 2.1.14.RELEASE (2018-07-27)
----------------------------------------------
* DATAES-463 - Release 2.1.14 (Ingalls SR14).
* DATAES-283 - Remove dependency to Commons Lang.
Changes in version 3.0.9.RELEASE (2018-07-26)
---------------------------------------------
* DATAES-470 - TransportClientFactoryBean does not parse clusterNodes correctly.
* DATAES-469 - Is org.elasticsearch:elasticsearch a necessary dependency?.
* DATAES-467 - No mapping found for [_score] in order to sort on.
* DATAES-465 - Release 3.0.9 (Kay SR9).
* DATAES-317 - Add query logging to ElasticsearchTemplate.
* DATAES-283 - Remove dependency to Commons Lang.
Changes in version 3.1.0.RC1 (2018-07-26)
-----------------------------------------
* DATAES-471 - Adapt to changes in immutable entities support.
* DATAES-470 - TransportClientFactoryBean does not parse clusterNodes correctly.
* DATAES-469 - Is org.elasticsearch:elasticsearch a necessary dependency?.
* DATAES-467 - No mapping found for [_score] in order to sort on.
* DATAES-464 - Add support for @ReadOnlyProperty to prevent properties from being written.
* DATAES-462 - Add support for mapping document scores to entities.
* DATAES-452 - Release 3.1 RC1 (Lovelace).
* DATAES-317 - Add query logging to ElasticsearchTemplate.
Changes in version 3.0.8.RELEASE (2018-06-13)
---------------------------------------------
* DATAES-460 - Avoid pulling in Netty 3 as dependency.
* DATAES-448 - Release 3.0.8 (Kay SR8).
* DATAES-420 - Analyzer of main field ignored when using @MultiField annotation.
* DATAES-312 - NullHandling.NULLS_LAST not working in query.sort.
Changes in version 2.1.13.RELEASE (2018-06-13)
----------------------------------------------
* DATAES-447 - Release 2.1.13 (Ingalls SR13).
Changes in version 3.1.0.M3 (2018-05-17)
----------------------------------------
* DATAES-451 - Adapt to SpEL extension API changes in Spring Data Commons.
* DATAES-440 - Release 3.1 M3 (Lovelace).
* DATAES-422 - Add support for IndicesOptions in search queries.
* DATAES-420 - Analyzer of main field ignored when using @MultiField annotation.
* DATAES-412 - Highlighted fields is not getting passed to the elastic search query.
* DATAES-363 - AbstractElasticsearchRepository.existsById(..) always returns true.
* DATAES-312 - NullHandling.NULLS_LAST not working in query.sort.
* DATAES-198 - @Version has no effect, so therefore is not useful with spring data elasticsearch.
Changes in version 3.0.7.RELEASE (2018-05-08)
---------------------------------------------
* DATAES-438 - Expected a boolean [true/false] for property [index] but got [not_analyzed].
* DATAES-437 - Release 3.0.7 (Kay SR7).
* DATAES-412 - Highlighted fields is not getting passed to the elastic search query.
* DATAES-402 - Paging not working correctly.
* DATAES-363 - AbstractElasticsearchRepository.existsById(..) always returns true.
* DATAES-198 - @Version has no effect, so therefore is not useful with spring data elasticsearch.
Changes in version 2.1.12.RELEASE (2018-05-08)
----------------------------------------------
* DATAES-436 - Release 2.1.12 (Ingalls SR12).
Changes in version 3.1.0.M2 (2018-04-13)
----------------------------------------
* DATAES-439 - Adapt to API changes in Spring Data Commons.
* DATAES-434 - Remove explicit declaration of Jackson library versions.
* DATAES-432 - Export composable repositories via CDI.
* DATAES-427 - Release 3.1 M2 (Lovelace).
Changes in version 3.0.6.RELEASE (2018-04-04)
---------------------------------------------
* DATAES-434 - Remove explicit declaration of Jackson library versions.
* DATAES-430 - Release 3.0.6 (Kay SR6).
Changes in version 2.1.11.RELEASE (2018-04-04)
----------------------------------------------
* DATAES-434 - Remove explicit declaration of Jackson library versions.
* DATAES-424 - Fix line endings.
* DATAES-423 - Release 2.1.11 (Ingalls SR11).
Changes in version 3.0.5.RELEASE (2018-02-28)
---------------------------------------------
* DATAES-429 - Release 3.0.5 (Kay SR5).
Changes in version 3.0.4.RELEASE (2018-02-19)
---------------------------------------------
* DATAES-425 - Release 3.0.4 (Kay SR4).
Changes in version 3.1.0.M1 (2018-02-06)
----------------------------------------
* DATAES-424 - Fix line endings.
* DATAES-414 - Reduce scope of Lo4j dependencies to test.
* DATAES-410 - Adapt API changes in Property in test cases.
* DATAES-401 - Release 3.1 M1 (Lovelace).
* DATAES-361 - log4j2.xml in classpath root of the library prevents Spring Boot's logging auto-configuration to work.
Changes in version 3.0.3.RELEASE (2018-01-24)
---------------------------------------------
* DATAES-424 - Fix line endings.
* DATAES-417 - Release 3.0.3 (Kay SR3).
Changes in version 2.1.10.RELEASE (2018-01-24)
----------------------------------------------
* DATAES-416 - Release 2.1.10 (Ingalls SR10).
Changes in version 3.0.2.RELEASE (2017-11-27)
---------------------------------------------
* DATAES-414 - Reduce scope of Lo4j dependencies to test.
* DATAES-411 - Release 3.0.2 (Kay SR2).
Changes in version 2.1.9.RELEASE (2017-11-27)
---------------------------------------------
* DATAES-408 - Ensure Spring 5 compatibility in Ingalls.
* DATAES-404 - Release 2.1.9 (Ingalls SR9).
Changes in version 3.0.1.RELEASE (2017-10-27)
---------------------------------------------
* DATAES-410 - Adapt API changes in Property in test cases.
* DATAES-400 - Release 3.0.1 (Kay SR1).
* DATAES-361 - log4j2.xml in classpath root of the library prevents Spring Boot's logging auto-configuration to work.
Changes in version 2.1.8.RELEASE (2017-10-11)
---------------------------------------------
* DATAES-391 - Release 2.1.8 (Ingalls SR8).
Changes in version 3.0.0.RELEASE (2017-10-02)
---------------------------------------------
* DATAES-397 - Add explicit automatic module name for Java 9.
* DATAES-395 - Upgrade to OpenWebBeans 2.0.1.
* DATAES-392 - Release 3.0 GA (Kay).
Changes in version 3.0.0.RC3 (2017-09-11)
-----------------------------------------
* DATAES-376 - Release 3.0 RC3 (Kay).
Changes in version 2.1.7.RELEASE (2017-09-11)
---------------------------------------------
* DATAES-378 - Release 2.1.7 (Ingalls SR7).
Changes in version 2.1.6.RELEASE (2017-07-26)
---------------------------------------------
* DATAES-374 - Release 2.1.6 (Ingalls SR6).
Changes in version 3.0.0.RC2 (2017-07-25)
-----------------------------------------
* DATAES-375 - Release 3.0 RC2 (Kay).
Changes in version 3.0.0.RC1 (2017-07-25)
-----------------------------------------
* DATAES-373 - Update ES to 5.5.0.
* DATAES-369 - Adapt to API changes in mapping subsystem.
* DATAES-359 - Release 3.0 RC1 (Kay).
* DATAES-274 - Jackson throws exception when deserializing Page.
Changes in version 2.1.5.RELEASE (2017-07-24)
---------------------------------------------
* DATAES-358 - Release 2.1.5 (Ingalls SR5).
Changes in version 3.0.0.M4 (2017-06-14)
----------------------------------------
* DATAES-353 - Release 3.0 M4 (Kay).
* DATAES-334 - Readme has broken jira link.
* DATAES-285 - Upgrade to Elasticsearch 5.0.
Changes in version 2.1.4.RELEASE (2017-06-08)
---------------------------------------------
* DATAES-349 - Release 2.1.4 (Ingalls SR4).
Changes in version 2.0.11.RELEASE (2017-06-07)
----------------------------------------------
* DATAES-348 - Release 2.0.11 (Hopper SR11).
Changes in version 3.0.0.M3 (2017-05-09)
----------------------------------------
* DATAES-352 - Adapt to API changes in CrudRepository.
* DATAES-350 - Adapt to moved CustomConversions to Spring Data Commons.
* DATAES-344 - Release 3.0 M3 (Kay).
Changes in version 2.0.10.RELEASE (2017-04-19)
----------------------------------------------
* DATAES-347 - Release 2.0.10 (Hopper SR10).
Changes in version 2.1.3.RELEASE (2017-04-19)
---------------------------------------------
* DATAES-346 - Release 2.1.3 (Ingalls SR3).
Changes in version 2.0.9.RELEASE (2017-04-19)
---------------------------------------------
* DATAES-336 - Release 2.0.9 (Hopper SR9).
Changes in version 2.1.2.RELEASE (2017-04-19)
---------------------------------------------
* DATAES-335 - Release 2.1.2 (Ingalls SR2).
+1 -1
View File
@@ -1,4 +1,4 @@
Spring Data Elasticsearch 3.1.3
Spring Data Elasticsearch 2.1.2
Copyright (c) [2013-2016] Pivotal Software, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License").
@@ -1,62 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you 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.elasticsearch.plugins;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collections;
import java.util.List;
/**
* A classloader that is a union over the parent core classloader and classloaders of extended plugins.
* Cloned from ES repository
* - that file is only available in ES server libs
* - and we need it o create a node client for unittests
*/
public class ExtendedPluginsClassLoader extends ClassLoader {
/** Loaders of plugins extended by a plugin. */
private final List<ClassLoader> extendedLoaders;
private ExtendedPluginsClassLoader(ClassLoader parent, List<ClassLoader> extendedLoaders) {
super(parent);
this.extendedLoaders = Collections.unmodifiableList(extendedLoaders);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
for (ClassLoader loader : extendedLoaders) {
try {
return loader.loadClass(name);
} catch (ClassNotFoundException e) {
// continue
}
}
throw new ClassNotFoundException(name);
}
/**
* Return a new classloader across the parent and extended loaders.
*/
public static ExtendedPluginsClassLoader create(ClassLoader parent, List<ClassLoader> extendedLoaders) {
return AccessController.doPrivileged((PrivilegedAction<ExtendedPluginsClassLoader>)
() -> new ExtendedPluginsClassLoader(parent, extendedLoaders));
}
}
@@ -1,73 +1,72 @@
/*
* Copyright 2014-2017 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.elasticsearch;
import static org.apache.commons.lang.RandomStringUtils.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
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.Author;
import org.springframework.data.elasticsearch.entities.Book;
import org.springframework.data.elasticsearch.repositories.book.SampleElasticSearchBookRepository;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Mohsin Husen
* @author Christoph Strobl
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/repository-test-nested-object-books.xml")
public class InnerObjectTests {
@Autowired private SampleElasticSearchBookRepository bookRepository;
@Autowired private ElasticsearchTemplate elasticsearchTemplate;
@Before
public void before() {
elasticsearchTemplate.deleteIndex(Book.class);
elasticsearchTemplate.createIndex(Book.class);
elasticsearchTemplate.putMapping(Book.class);
elasticsearchTemplate.refresh(Book.class);
}
@Test
public void shouldIndexInnerObject() {
// given
String id = randomAlphanumeric(5);
Book book = new Book();
book.setId(id);
book.setName("xyz");
Author author = new Author();
author.setId("1");
author.setName("ABC");
book.setAuthor(author);
// when
bookRepository.save(book);
// then
assertThat(bookRepository.findById(id), is(notNullValue()));
}
}
/*
* Copyright 2014-2016 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.elasticsearch;
import static org.apache.commons.lang.RandomStringUtils.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
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.Author;
import org.springframework.data.elasticsearch.entities.Book;
import org.springframework.data.elasticsearch.repositories.book.SampleElasticSearchBookRepository;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Mohsin Husen
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/repository-test-nested-object.xml")
public class InnerObjectTests {
@Autowired
private SampleElasticSearchBookRepository bookRepository;
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Before
public void before() {
elasticsearchTemplate.deleteIndex(Book.class);
elasticsearchTemplate.createIndex(Book.class);
elasticsearchTemplate.putMapping(Book.class);
elasticsearchTemplate.refresh(Book.class);
}
@Test
public void shouldIndexInnerObject() {
// given
String id = randomAlphanumeric(5);
Book book = new Book();
book.setId(id);
book.setName("xyz");
Author author = new Author();
author.setId("1");
author.setName("ABC");
book.setAuthor(author);
// when
bookRepository.save(book);
// then
assertThat(bookRepository.findOne(id), is(notNullValue()));
}
}
@@ -1,385 +1,387 @@
/*
* Copyright 2013-2017 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.elasticsearch;
import static org.apache.commons.lang.RandomStringUtils.*;
import static org.elasticsearch.index.query.QueryBuilders.*;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.GetQuery;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.data.elasticsearch.entities.Author;
import org.springframework.data.elasticsearch.entities.Book;
import org.springframework.data.elasticsearch.entities.Car;
import org.springframework.data.elasticsearch.entities.GirlFriend;
import org.springframework.data.elasticsearch.entities.Person;
import org.springframework.data.elasticsearch.entities.PersonMultipleLevelNested;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/repository-test-nested-object.xml")
public class NestedObjectTests {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Before
public void before() {
elasticsearchTemplate.deleteIndex(Book.class);
elasticsearchTemplate.createIndex(Book.class);
elasticsearchTemplate.putMapping(Book.class);
elasticsearchTemplate.refresh(Book.class);
elasticsearchTemplate.deleteIndex(Person.class);
elasticsearchTemplate.createIndex(Person.class);
elasticsearchTemplate.putMapping(Person.class);
elasticsearchTemplate.refresh(Person.class);
elasticsearchTemplate.deleteIndex(PersonMultipleLevelNested.class);
elasticsearchTemplate.createIndex(PersonMultipleLevelNested.class);
elasticsearchTemplate.putMapping(PersonMultipleLevelNested.class);
elasticsearchTemplate.refresh(PersonMultipleLevelNested.class);
}
@Test
public void shouldIndexInitialLevelNestedObject() {
final List<Car> cars = new ArrayList<>();
final Car saturn = new Car();
saturn.setName("Saturn");
saturn.setModel("SL");
final Car subaru = new Car();
subaru.setName("Subaru");
subaru.setModel("Imprezza");
final Car ford = new Car();
ford.setName("Ford");
ford.setModel("Focus");
cars.add(saturn);
cars.add(subaru);
cars.add(ford);
final Person foo = new Person();
foo.setName("Foo");
foo.setId("1");
foo.setCar(cars);
final Car car = new Car();
car.setName("Saturn");
car.setModel("Imprezza");
final Person bar = new Person();
bar.setId("2");
bar.setName("Bar");
bar.setCar(Arrays.asList(car));
final List<IndexQuery> indexQueries = new ArrayList<>();
final IndexQuery indexQuery1 = new IndexQuery();
indexQuery1.setId(foo.getId());
indexQuery1.setObject(foo);
final IndexQuery indexQuery2 = new IndexQuery();
indexQuery2.setId(bar.getId());
indexQuery2.setObject(bar);
indexQueries.add(indexQuery1);
indexQueries.add(indexQuery2);
elasticsearchTemplate.putMapping(Person.class);
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(Person.class);
final QueryBuilder builder = nestedQuery("car", boolQuery().must(termQuery("car.name", "saturn")).must(termQuery("car.model", "imprezza")), ScoreMode.None);
final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder).build();
final List<Person> persons = elasticsearchTemplate.queryForList(searchQuery, Person.class);
assertThat(persons.size(), is(1));
}
@Test
public void shouldIndexMultipleLevelNestedObject() {
//given
final List<IndexQuery> indexQueries = createPerson();
//when
elasticsearchTemplate.putMapping(PersonMultipleLevelNested.class);
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(PersonMultipleLevelNested.class);
//then
final GetQuery getQuery = new GetQuery();
getQuery.setId("1");
final PersonMultipleLevelNested personIndexed = elasticsearchTemplate.queryForObject(getQuery, PersonMultipleLevelNested.class);
assertThat(personIndexed, is(notNullValue()));
}
@Test
public void shouldIndexMultipleLevelNestedObjectWithIncludeInParent() {
//given
final List<IndexQuery> indexQueries = createPerson();
//when
elasticsearchTemplate.putMapping(PersonMultipleLevelNested.class);
elasticsearchTemplate.bulkIndex(indexQueries);
// then
final Map mapping = elasticsearchTemplate.getMapping(PersonMultipleLevelNested.class);
assertThat(mapping, is(notNullValue()));
final Map propertyMap = (Map) mapping.get("properties");
assertThat(propertyMap, is(notNullValue()));
final Map bestCarsAttributes = (Map) propertyMap.get("bestCars");
assertThat(bestCarsAttributes.get("include_in_parent"), is(notNullValue()));
}
@Test
public void shouldSearchUsingNestedQueryOnMultipleLevelNestedObject() {
//given
final List<IndexQuery> indexQueries = createPerson();
//when
elasticsearchTemplate.putMapping(PersonMultipleLevelNested.class);
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(PersonMultipleLevelNested.class);
//then
final BoolQueryBuilder builder = boolQuery();
builder.must(nestedQuery("girlFriends", termQuery("girlFriends.type", "temp"),ScoreMode.None))
.must(nestedQuery("girlFriends.cars", termQuery("girlFriends.cars.name", "Ford".toLowerCase()),ScoreMode.None));
final SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(builder)
.build();
final Page<PersonMultipleLevelNested> personIndexed = elasticsearchTemplate.queryForPage(searchQuery, PersonMultipleLevelNested.class);
assertThat(personIndexed, is(notNullValue()));
assertThat(personIndexed.getTotalElements(), is(1L));
assertThat(personIndexed.getContent().get(0).getId(), is("1"));
}
private List<IndexQuery> createPerson() {
final PersonMultipleLevelNested person1 = new PersonMultipleLevelNested();
person1.setId("1");
person1.setName("name");
final Car saturn = new Car();
saturn.setName("Saturn");
saturn.setModel("SL");
final Car subaru = new Car();
subaru.setName("Subaru");
subaru.setModel("Imprezza");
final Car car = new Car();
car.setName("Saturn");
car.setModel("Imprezza");
final Car ford = new Car();
ford.setName("Ford");
ford.setModel("Focus");
final GirlFriend permanent = new GirlFriend();
permanent.setName("permanent");
permanent.setType("permanent");
permanent.setCars(Arrays.asList(saturn, subaru));
final GirlFriend temp = new GirlFriend();
temp.setName("temp");
temp.setType("temp");
temp.setCars(Arrays.asList(car, ford));
person1.setGirlFriends(Arrays.asList(permanent, temp));
final IndexQuery indexQuery1 = new IndexQuery();
indexQuery1.setId(person1.getId());
indexQuery1.setObject(person1);
final PersonMultipleLevelNested person2 = new PersonMultipleLevelNested();
person2.setId("2");
person2.setName("name");
person2.setGirlFriends(Arrays.asList(permanent));
final IndexQuery indexQuery2 = new IndexQuery();
indexQuery2.setId(person2.getId());
indexQuery2.setObject(person2);
final List<IndexQuery> indexQueries = new ArrayList<>();
indexQueries.add(indexQuery1);
indexQueries.add(indexQuery2);
return indexQueries;
}
@Test
public void shouldSearchBooksForPersonInitialLevelNestedType() {
final List<Car> cars = new ArrayList<>();
final Car saturn = new Car();
saturn.setName("Saturn");
saturn.setModel("SL");
final Car subaru = new Car();
subaru.setName("Subaru");
subaru.setModel("Imprezza");
final Car ford = new Car();
ford.setName("Ford");
ford.setModel("Focus");
cars.add(saturn);
cars.add(subaru);
cars.add(ford);
final Book java = new Book();
java.setId("1");
java.setName("java");
final Author javaAuthor = new Author();
javaAuthor.setId("1");
javaAuthor.setName("javaAuthor");
java.setAuthor(javaAuthor);
final Book spring = new Book();
spring.setId("2");
spring.setName("spring");
final Author springAuthor = new Author();
springAuthor.setId("2");
springAuthor.setName("springAuthor");
spring.setAuthor(springAuthor);
final Person foo = new Person();
foo.setName("Foo");
foo.setId("1");
foo.setCar(cars);
foo.setBooks(Arrays.asList(java, spring));
final Car car = new Car();
car.setName("Saturn");
car.setModel("Imprezza");
final Person bar = new Person();
bar.setId("2");
bar.setName("Bar");
bar.setCar(Arrays.asList(car));
final List<IndexQuery> indexQueries = new ArrayList<>();
final IndexQuery indexQuery1 = new IndexQuery();
indexQuery1.setId(foo.getId());
indexQuery1.setObject(foo);
final IndexQuery indexQuery2 = new IndexQuery();
indexQuery2.setId(bar.getId());
indexQuery2.setObject(bar);
indexQueries.add(indexQuery1);
indexQueries.add(indexQuery2);
elasticsearchTemplate.putMapping(Person.class);
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(Person.class);
final QueryBuilder builder = nestedQuery("books", boolQuery().must(termQuery("books.name", "java")), ScoreMode.None);
final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder).build();
final List<Person> persons = elasticsearchTemplate.queryForList(searchQuery, Person.class);
assertThat(persons.size(), is(1));
}
/*
DATAES-73
*/
@Test
public void shouldIndexAndSearchMapAsNestedType() {
//given
final Book book1 = new Book();
final Book book2 = new Book();
book1.setId(randomNumeric(5));
book1.setName("testBook1");
book2.setId(randomNumeric(5));
book2.setName("testBook2");
final Map<Integer, Collection<String>> map1 = new HashMap<>();
map1.put(1, Arrays.asList("test1", "test2"));
final Map<Integer, Collection<String>> map2 = new HashMap<>();
map2.put(1, Arrays.asList("test3", "test4"));
book1.setBuckets(map1);
book2.setBuckets(map2);
final List<IndexQuery> indexQueries = new ArrayList<>();
final IndexQuery indexQuery1 = new IndexQuery();
indexQuery1.setId(book1.getId());
indexQuery1.setObject(book1);
final IndexQuery indexQuery2 = new IndexQuery();
indexQuery2.setId(book2.getId());
indexQuery2.setObject(book2);
indexQueries.add(indexQuery1);
indexQueries.add(indexQuery2);
//when
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(Book.class);
//then
final SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(nestedQuery("buckets", termQuery("buckets.1", "test3"),ScoreMode.None))
.build();
final Page<Book> books = elasticsearchTemplate.queryForPage(searchQuery, Book.class);
assertThat(books.getContent().size(), is(1));
assertThat(books.getContent().get(0).getId(), is(book2.getId()));
}
}
/*
* Copyright 2013-2016 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.elasticsearch;
import static org.apache.commons.lang.RandomStringUtils.randomNumeric;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.nestedQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.GetQuery;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.data.elasticsearch.entities.Author;
import org.springframework.data.elasticsearch.entities.Book;
import org.springframework.data.elasticsearch.entities.Car;
import org.springframework.data.elasticsearch.entities.GirlFriend;
import org.springframework.data.elasticsearch.entities.Person;
import org.springframework.data.elasticsearch.entities.PersonMultipleLevelNested;
import org.springframework.data.geo.Point;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/repository-test-nested-object.xml")
public class NestedObjectTests {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Before
public void before() {
elasticsearchTemplate.deleteIndex(Book.class);
elasticsearchTemplate.createIndex(Book.class);
elasticsearchTemplate.putMapping(Book.class);
elasticsearchTemplate.refresh(Book.class);
elasticsearchTemplate.deleteIndex(Person.class);
elasticsearchTemplate.createIndex(Person.class);
elasticsearchTemplate.putMapping(Person.class);
elasticsearchTemplate.refresh(Person.class);
elasticsearchTemplate.deleteIndex(PersonMultipleLevelNested.class);
elasticsearchTemplate.createIndex(PersonMultipleLevelNested.class);
elasticsearchTemplate.putMapping(PersonMultipleLevelNested.class);
elasticsearchTemplate.refresh(PersonMultipleLevelNested.class);
}
@Test
public void shouldIndexInitialLevelNestedObject() {
final List<Car> cars = new ArrayList<Car>();
final Car saturn = new Car();
saturn.setName("Saturn");
saturn.setModel("SL");
final Car subaru = new Car();
subaru.setName("Subaru");
subaru.setModel("Imprezza");
final Car ford = new Car();
ford.setName("Ford");
ford.setModel("Focus");
cars.add(saturn);
cars.add(subaru);
cars.add(ford);
final Person foo = new Person();
foo.setName("Foo");
foo.setId("1");
foo.setCar(cars);
final Car car = new Car();
car.setName("Saturn");
car.setModel("Imprezza");
final Person bar = new Person();
bar.setId("2");
bar.setName("Bar");
bar.setCar(Arrays.asList(car));
final List<IndexQuery> indexQueries = new ArrayList<IndexQuery>();
final IndexQuery indexQuery1 = new IndexQuery();
indexQuery1.setId(foo.getId());
indexQuery1.setObject(foo);
final IndexQuery indexQuery2 = new IndexQuery();
indexQuery2.setId(bar.getId());
indexQuery2.setObject(bar);
indexQueries.add(indexQuery1);
indexQueries.add(indexQuery2);
elasticsearchTemplate.putMapping(Person.class);
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(Person.class);
final QueryBuilder builder = nestedQuery("car", boolQuery().must(termQuery("car.name", "saturn")).must(termQuery("car.model", "imprezza")));
final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder).build();
final List<Person> persons = elasticsearchTemplate.queryForList(searchQuery, Person.class);
assertThat(persons.size(), is(1));
}
@Test
public void shouldIndexMultipleLevelNestedObject() {
//given
final List<IndexQuery> indexQueries = createPerson();
//when
elasticsearchTemplate.putMapping(PersonMultipleLevelNested.class);
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(PersonMultipleLevelNested.class);
//then
final GetQuery getQuery = new GetQuery();
getQuery.setId("1");
final PersonMultipleLevelNested personIndexed = elasticsearchTemplate.queryForObject(getQuery, PersonMultipleLevelNested.class);
assertThat(personIndexed, is(notNullValue()));
}
@Test
public void shouldIndexMultipleLevelNestedObjectWithIncludeInParent() {
//given
final List<IndexQuery> indexQueries = createPerson();
//when
elasticsearchTemplate.putMapping(PersonMultipleLevelNested.class);
elasticsearchTemplate.bulkIndex(indexQueries);
// then
final Map mapping = elasticsearchTemplate.getMapping(PersonMultipleLevelNested.class);
assertThat(mapping, is(notNullValue()));
final Map propertyMap = (Map) mapping.get("properties");
assertThat(propertyMap, is(notNullValue()));
final Map bestCarsAttributes = (Map) propertyMap.get("bestCars");
assertThat(bestCarsAttributes.get("include_in_parent"), is(notNullValue()));
}
@Test
public void shouldSearchUsingNestedQueryOnMultipleLevelNestedObject() {
//given
final List<IndexQuery> indexQueries = createPerson();
//when
elasticsearchTemplate.putMapping(PersonMultipleLevelNested.class);
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(PersonMultipleLevelNested.class);
//then
final BoolQueryBuilder builder = boolQuery();
builder.must(nestedQuery("girlFriends", termQuery("girlFriends.type", "temp")))
.must(nestedQuery("girlFriends.cars", termQuery("girlFriends.cars.name", "Ford".toLowerCase())));
final SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(builder)
.build();
final Page<PersonMultipleLevelNested> personIndexed = elasticsearchTemplate.queryForPage(searchQuery, PersonMultipleLevelNested.class);
assertThat(personIndexed, is(notNullValue()));
assertThat(personIndexed.getTotalElements(), is(1L));
assertThat(personIndexed.getContent().get(0).getId(), is("1"));
}
private List<IndexQuery> createPerson() {
final PersonMultipleLevelNested person1 = new PersonMultipleLevelNested();
person1.setId("1");
person1.setName("name");
final Car saturn = new Car();
saturn.setName("Saturn");
saturn.setModel("SL");
final Car subaru = new Car();
subaru.setName("Subaru");
subaru.setModel("Imprezza");
final Car car = new Car();
car.setName("Saturn");
car.setModel("Imprezza");
final Car ford = new Car();
ford.setName("Ford");
ford.setModel("Focus");
final GirlFriend permanent = new GirlFriend();
permanent.setName("permanent");
permanent.setType("permanent");
permanent.setCars(Arrays.asList(saturn, subaru));
final GirlFriend temp = new GirlFriend();
temp.setName("temp");
temp.setType("temp");
temp.setCars(Arrays.asList(car, ford));
person1.setGirlFriends(Arrays.asList(permanent, temp));
final IndexQuery indexQuery1 = new IndexQuery();
indexQuery1.setId(person1.getId());
indexQuery1.setObject(person1);
final PersonMultipleLevelNested person2 = new PersonMultipleLevelNested();
person2.setId("2");
person2.setName("name");
person2.setGirlFriends(Arrays.asList(permanent));
final IndexQuery indexQuery2 = new IndexQuery();
indexQuery2.setId(person2.getId());
indexQuery2.setObject(person2);
final List<IndexQuery> indexQueries = new ArrayList<IndexQuery>();
indexQueries.add(indexQuery1);
indexQueries.add(indexQuery2);
return indexQueries;
}
@Test
public void shouldSearchBooksForPersonInitialLevelNestedType() {
final List<Car> cars = new ArrayList<Car>();
final Car saturn = new Car();
saturn.setName("Saturn");
saturn.setModel("SL");
final Car subaru = new Car();
subaru.setName("Subaru");
subaru.setModel("Imprezza");
final Car ford = new Car();
ford.setName("Ford");
ford.setModel("Focus");
cars.add(saturn);
cars.add(subaru);
cars.add(ford);
final Book java = new Book();
java.setId("1");
java.setName("java");
final Author javaAuthor = new Author();
javaAuthor.setId("1");
javaAuthor.setName("javaAuthor");
java.setAuthor(javaAuthor);
final Book spring = new Book();
spring.setId("2");
spring.setName("spring");
final Author springAuthor = new Author();
springAuthor.setId("2");
springAuthor.setName("springAuthor");
spring.setAuthor(springAuthor);
final Person foo = new Person();
foo.setName("Foo");
foo.setId("1");
foo.setCar(cars);
foo.setBooks(Arrays.asList(java, spring));
final Car car = new Car();
car.setName("Saturn");
car.setModel("Imprezza");
final Person bar = new Person();
bar.setId("2");
bar.setName("Bar");
bar.setCar(Arrays.asList(car));
final List<IndexQuery> indexQueries = new ArrayList<IndexQuery>();
final IndexQuery indexQuery1 = new IndexQuery();
indexQuery1.setId(foo.getId());
indexQuery1.setObject(foo);
final IndexQuery indexQuery2 = new IndexQuery();
indexQuery2.setId(bar.getId());
indexQuery2.setObject(bar);
indexQueries.add(indexQuery1);
indexQueries.add(indexQuery2);
elasticsearchTemplate.putMapping(Person.class);
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(Person.class);
final QueryBuilder builder = nestedQuery("books", boolQuery().must(termQuery("books.name", "java")));
final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder).build();
final List<Person> persons = elasticsearchTemplate.queryForList(searchQuery, Person.class);
assertThat(persons.size(), is(1));
}
/*
DATAES-73
*/
@Test
public void shouldIndexAndSearchMapAsNestedType() {
//given
final Book book1 = new Book();
final Book book2 = new Book();
book1.setId(randomNumeric(5));
book1.setName("testBook1");
book2.setId(randomNumeric(5));
book2.setName("testBook2");
final Map<Integer, Collection<String>> map1 = new HashMap<Integer, Collection<String>>();
map1.put(1, Arrays.asList("test1", "test2"));
final Map<Integer, Collection<String>> map2 = new HashMap<Integer, Collection<String>>();
map2.put(1, Arrays.asList("test3", "test4"));
book1.setBuckets(map1);
book2.setBuckets(map2);
final List<IndexQuery> indexQueries = new ArrayList<IndexQuery>();
final IndexQuery indexQuery1 = new IndexQuery();
indexQuery1.setId(book1.getId());
indexQuery1.setObject(book1);
final IndexQuery indexQuery2 = new IndexQuery();
indexQuery2.setId(book2.getId());
indexQuery2.setObject(book2);
indexQueries.add(indexQuery1);
indexQueries.add(indexQuery2);
//when
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(Book.class);
//then
final SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(nestedQuery("buckets", termQuery("buckets.1", "test3")))
.build();
final Page<Book> books = elasticsearchTemplate.queryForPage(searchQuery, Book.class);
assertThat(books.getContent().size(), is(1));
assertThat(books.getContent().get(0).getId(), is(book2.getId()));
}
}
@@ -1,35 +1,35 @@
/*
* Copyright 2013 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.elasticsearch;
import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.elasticsearch.repositories.nondocument.NonDocumentEntityRepository;
/**
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class NonDocumentEntityTests {
@Test(expected = BeanCreationException.class)
public void shouldNotInitialiseRepositoryWithNonDocument() {
// when
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/repository-non-document-entity.xml");
ctx.getBean(NonDocumentEntityRepository.class);
}
}
/*
* Copyright 2013 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.elasticsearch;
import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.elasticsearch.repositories.nondocument.NonDocumentEntityRepository;
/**
* @author Rizwan Idrees
* @author Mohsin Husen
*/
public class NonDocumentEntityTests {
@Test(expected = BeanCreationException.class)
public void shouldNotInitialiseRepositoryWithNonDocument() {
// when
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/repository-non-document-entity.xml");
ctx.getBean(NonDocumentEntityRepository.class);
}
}
@@ -0,0 +1,139 @@
/*
* Copyright 2013 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.elasticsearch;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Version;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.ScriptedField;
/**
* @author Rizwan Idrees
* @author Mohsin Husen
*/
@Document(indexName = "test-index", type = "test-type", shards = 1, replicas = 0, refreshInterval = "-1")
public class SampleEntity {
@Id
private String id;
private String type;
private String message;
private int rate;
@ScriptedField
private Long scriptedRate;
private boolean available;
private String highlightedMessage;
@Version
private Long version;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getRate() {
return rate;
}
public void setRate(int rate) {
this.rate = rate;
}
public Long getScriptedRate() {
return scriptedRate;
}
public void setScriptedRate(Long scriptedRate) {
this.scriptedRate = scriptedRate;
}
public boolean isAvailable() {
return available;
}
public void setAvailable(boolean available) {
this.available = available;
}
public String getHighlightedMessage() {
return highlightedMessage;
}
public void setHighlightedMessage(String highlightedMessage) {
this.highlightedMessage = highlightedMessage;
}
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof SampleEntity)) {
return false;
}
if (this == obj) {
return true;
}
SampleEntity rhs = (SampleEntity) obj;
return new EqualsBuilder().append(this.id, rhs.id).append(this.type, rhs.type).append(this.message, rhs.message)
.append(this.rate, rhs.rate).append(this.available, rhs.available).append(this.version, rhs.version).isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder().append(id).append(type).append(message).append(rate).append(available).append(version)
.toHashCode();
}
@Override
public String toString() {
return "SampleEntity{" +
"id='" + id + '\'' +
", type='" + type + '\'' +
", message='" + message + '\'' +
", rate=" + rate +
", available=" + available +
", highlightedMessage='" + highlightedMessage + '\'' +
", version=" + version +
'}';
}
}
@@ -0,0 +1,140 @@
/*
* Copyright 2013 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.elasticsearch;
import java.util.UUID;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Version;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.ScriptedField;
/**
* @author Gad Akuka
*/
@Document(indexName = "test-index", type = "test-type", indexStoreType = "memory", shards = 1, replicas = 0, refreshInterval = "-1")
public class SampleEntityUUIDKeyed {
@Id
private UUID id;
private String type;
private String message;
private int rate;
@ScriptedField
private Long scriptedRate;
private boolean available;
private String highlightedMessage;
@Version
private Long version;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getRate() {
return rate;
}
public void setRate(int rate) {
this.rate = rate;
}
public Long getScriptedRate() {
return scriptedRate;
}
public void setScriptedRate(Long scriptedRate) {
this.scriptedRate = scriptedRate;
}
public boolean isAvailable() {
return available;
}
public void setAvailable(boolean available) {
this.available = available;
}
public String getHighlightedMessage() {
return highlightedMessage;
}
public void setHighlightedMessage(String highlightedMessage) {
this.highlightedMessage = highlightedMessage;
}
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof SampleEntityUUIDKeyed)) {
return false;
}
if (this == obj) {
return true;
}
SampleEntityUUIDKeyed rhs = (SampleEntityUUIDKeyed) obj;
return new EqualsBuilder().append(this.id, rhs.id).append(this.type, rhs.type).append(this.message, rhs.message)
.append(this.rate, rhs.rate).append(this.available, rhs.available).append(this.version, rhs.version).isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder().append(id).append(type).append(message).append(rate).append(available).append(version)
.toHashCode();
}
@Override
public String toString() {
return "SampleEntity{" +
"id='" + id + '\'' +
", type='" + type + '\'' +
", message='" + message + '\'' +
", rate=" + rate +
", available=" + available +
", highlightedMessage='" + highlightedMessage + '\'' +
", version=" + version +
'}';
}
}
@@ -15,35 +15,24 @@
*/
package org.springframework.data.elasticsearch;
import static org.elasticsearch.node.NodeBuilder.*;
import java.util.UUID;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.node.NodeValidationException;
import org.elasticsearch.transport.Netty4Plugin;
import org.springframework.data.elasticsearch.client.NodeClientFactoryBean;
import static java.util.Arrays.*;
/**
* @author Mohsin Husen
* @author Artur Konczak
* @author Ilkang Na
*/
public class Utils {
public static Client getNodeClient() throws NodeValidationException {
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();
public static NodeClient getNodeClient() {
return (NodeClient) nodeBuilder().settings(Settings.builder()
.put("http.enabled", "false")
.put("path.data", "target/elasticsearchTestData")
.put("path.home", "src/test/resources/test-home-dir"))
.clusterName(UUID.randomUUID().toString()).local(true).node()
.client();
}
}
@@ -1,90 +0,0 @@
/*
* Copyright 2018 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.elasticsearch.client;
import static org.assertj.core.api.Assertions.*;
import java.util.List;
import org.elasticsearch.common.transport.TransportAddress;
import org.junit.Test;
/**
* Unit tests for {@link ClusterNodes}.
*
* @author Oliver Gierke
*/
public class ClusterNodesUnitTests {
@Test // DATAES-470
public void parsesSingleClusterNode() {
ClusterNodes nodes = ClusterNodes.DEFAULT;
assertThat(nodes).hasSize(1) //
.first().satisfies(it -> {
assertThat(it.getAddress()).isEqualTo("127.0.0.1");
assertThat(it.getPort()).isEqualTo(9300);
});
}
@Test // DATAES-470
public void parsesMultiClusterNode() {
ClusterNodes nodes = ClusterNodes.of("127.0.0.1:1234,10.1.0.1:5678");
assertThat(nodes.stream()).hasSize(2); //
assertThat(nodes.stream()).element(0).satisfies(it -> {
assertThat(it.getAddress()).isEqualTo("127.0.0.1");
assertThat(it.getPort()).isEqualTo(1234);
});
assertThat(nodes.stream()).element(1).satisfies(it -> {
assertThat(it.getAddress()).isEqualTo("10.1.0.1");
assertThat(it.getPort()).isEqualTo(5678);
});
}
@Test // DATAES-470
public void rejectsEmptyHostName() {
assertThatExceptionOfType(IllegalArgumentException.class) //
.isThrownBy(() -> ClusterNodes.of(":8080")) //
.withMessageContaining("host");
}
@Test // DATAES-470
public void rejectsEmptyPort() {
assertThatExceptionOfType(IllegalArgumentException.class) //
.isThrownBy(() -> ClusterNodes.of("localhost:")) //
.withMessageContaining("port");
}
@Test // DATAES-470
public void rejectsMissingPort() {
assertThatExceptionOfType(IllegalArgumentException.class) //
.isThrownBy(() -> ClusterNodes.of("localhost")) //
.withMessageContaining("host:port");
}
@Test // DATAES-470
public void rejectsUnresolvableHost() {
assertThatExceptionOfType(IllegalArgumentException.class) //
.isThrownBy(() -> ClusterNodes.of("mylocalhost:80"));
}
}
@@ -1,55 +1,62 @@
/*
* Copyright 2013 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.elasticsearch.config;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.elasticsearch.client.TransportClientFactoryBean;
import org.springframework.data.elasticsearch.repositories.sample.SampleElasticsearchRepository;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Rizwan Idrees
* @author Mohsin Husen
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("namespace.xml")
public class ElasticsearchNamespaceHandlerTests {
@Autowired
private ApplicationContext context;
@Test
public void shouldCreateTransportClient() {
assertThat(context.getBean(TransportClientFactoryBean.class), is(notNullValue()));
assertThat(context.getBean(TransportClientFactoryBean.class), is(instanceOf(TransportClientFactoryBean.class)));
}
@Test
public void shouldCreateRepository() {
assertThat(context.getBean(TransportClientFactoryBean.class), is(notNullValue()));
assertThat(context.getBean(SampleElasticsearchRepository.class),
is(instanceOf(SampleElasticsearchRepository.class)));
}
}
/*
* Copyright 2013 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.elasticsearch.config;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.elasticsearch.client.NodeClientFactoryBean;
import org.springframework.data.elasticsearch.client.TransportClientFactoryBean;
import org.springframework.data.elasticsearch.repositories.sample.SampleElasticsearchRepository;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Rizwan Idrees
* @author Mohsin Husen
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("namespace.xml")
public class ElasticsearchNamespaceHandlerTests {
@Autowired
private ApplicationContext context;
@Test
public void shouldCreatesNodeClient() {
assertThat(context.getBean(NodeClientFactoryBean.class), is(notNullValue()));
assertThat(context.getBean(NodeClientFactoryBean.class), is(instanceOf(NodeClientFactoryBean.class)));
}
@Test
public void shouldCreateTransportClient() {
assertThat(context.getBean(TransportClientFactoryBean.class), is(notNullValue()));
assertThat(context.getBean(TransportClientFactoryBean.class), is(instanceOf(TransportClientFactoryBean.class)));
}
@Test
public void shouldCreateRepository() {
assertThat(context.getBean(TransportClientFactoryBean.class), is(notNullValue()));
assertThat(context.getBean(SampleElasticsearchRepository.class),
is(instanceOf(SampleElasticsearchRepository.class)));
}
}
@@ -20,7 +20,6 @@ import static org.junit.Assert.*;
import java.util.Arrays;
import org.elasticsearch.node.NodeValidationException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeansException;
@@ -63,7 +62,7 @@ public class EnableElasticsearchRepositoriesTests implements ApplicationContextA
static class Config {
@Bean
public ElasticsearchOperations elasticsearchTemplate() throws NodeValidationException {
public ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchTemplate(Utils.getNodeClient());
}
}
@@ -15,9 +15,6 @@
*/
package org.springframework.data.elasticsearch.config;
import static org.junit.Assert.*;
import org.elasticsearch.node.NodeValidationException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -32,6 +29,8 @@ import org.springframework.data.repository.Repository;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.assertNotNull;
/**
* @author Kevin Leturc
*/
@@ -45,7 +44,7 @@ public class EnableNestedElasticsearchRepositoriesTests {
static class Config {
@Bean
public ElasticsearchOperations elasticsearchTemplate() throws NodeValidationException {
public ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchTemplate(Utils.getNodeClient());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014-2016 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.
@@ -19,29 +19,21 @@ import static org.apache.commons.lang.RandomStringUtils.*;
import static org.elasticsearch.index.query.QueryBuilders.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.elasticsearch.cluster.metadata.AliasMetaData;
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.query.AliasBuilder;
import org.springframework.data.elasticsearch.core.query.AliasQuery;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.data.elasticsearch.entities.SampleEntity;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Mohsin Husen
* @author Ilkang Na
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:elasticsearch-template-test.xml")
@@ -56,7 +48,7 @@ public class AliasTests {
@Before
public void before() {
Map<String, Object> settings = new HashMap<>();
Map<String, Object> settings = new HashMap<String, Object>();
settings.put("index.refresh_interval", "-1");
settings.put("index.number_of_replicas", "0");
settings.put("index.number_of_shards", "2");
@@ -102,7 +94,7 @@ public class AliasTests {
// then
elasticsearchTemplate.removeAlias(aliasQuery);
aliases = elasticsearchTemplate.queryForAlias(indexName);
assertThat(aliases, anyOf(is(nullValue()), hasSize(0)));
assertThat(aliases, is(nullValue()));
}
/*
@@ -29,13 +29,13 @@ public class CustomEntityMapper implements EntityMapper {
@Override
public String mapToString(Object object) throws IOException {
//mapping Object to text
//mapping Object to String
return null;
}
@Override
public <T> T mapToObject(String source, Class<T> clazz) throws IOException {
//mapping text to Object
//mapping String to Object
return null;
}
}
@@ -20,6 +20,7 @@ import java.util.LinkedList;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2018 the original author or authors.
* Copyright 2013-2014 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.
@@ -15,17 +15,15 @@
*/
package org.springframework.data.elasticsearch.core;
import static org.assertj.core.api.Assertions.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.io.IOException;
import java.util.Locale;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.annotation.ReadOnlyProperty;
import org.springframework.data.annotation.Transient;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import org.springframework.data.elasticsearch.entities.Car;
import org.springframework.data.elasticsearch.entities.GeoEntity;
import org.springframework.data.geo.Point;
@@ -33,7 +31,6 @@ import org.springframework.data.geo.Point;
/**
* @author Artur Konczak
* @author Mohsin Husen
* @author Oliver Gierke
*/
public class DefaultEntityMapperTests {
@@ -44,7 +41,7 @@ public class DefaultEntityMapperTests {
@Before
public void init() {
entityMapper = new DefaultEntityMapper(new SimpleElasticsearchMappingContext());
entityMapper = new DefaultEntityMapper();
}
@Test
@@ -55,7 +52,7 @@ public class DefaultEntityMapperTests {
String jsonResult = entityMapper.mapToString(Car.builder().model(CAR_MODEL).name(CAR_NAME).build());
//Then
assertThat(jsonResult).isEqualTo(JSON_STRING);
assertThat(jsonResult, is(JSON_STRING));
}
@Test
@@ -66,14 +63,15 @@ public class DefaultEntityMapperTests {
Car result = entityMapper.mapToObject(JSON_STRING, Car.class);
//Then
assertThat(result.getName()).isEqualTo(CAR_NAME);
assertThat(result.getModel()).isEqualTo(CAR_MODEL);
assertThat(result.getName(), is(CAR_NAME));
assertThat(result.getModel(), is(CAR_MODEL));
}
@Test
public void shouldMapGeoPointElasticsearchNames() throws IOException {
//given
final Point point = new Point(10, 20);
final int radius = 10;
final String pointAsString = point.getX() + "," + point.getY();
final double[] pointAsArray = {point.getX(), point.getY()};
final GeoEntity geoEntity = GeoEntity.builder()
@@ -83,43 +81,13 @@ public class DefaultEntityMapperTests {
String jsonResult = entityMapper.mapToString(geoEntity);
//then
assertThat(jsonResult).contains(pointTemplate("pointA", point));
assertThat(jsonResult).contains(pointTemplate("pointB", point));
assertThat(jsonResult).contains(String.format(Locale.ENGLISH, "\"%s\":\"%s\"", "pointC", pointAsString));
assertThat(jsonResult).contains(String.format(Locale.ENGLISH, "\"%s\":[%.1f,%.1f]", "pointD", pointAsArray[0], pointAsArray[1]));
}
@Test // DATAES-464
public void ignoresReadOnlyProperties() throws IOException {
// given
Sample sample = new Sample();
sample.readOnly = "readOnly";
sample.property = "property";
sample.transientProperty = "transient";
sample.annotatedTransientProperty = "transient";
// when
String result = entityMapper.mapToString(sample);
// then
assertThat(result).contains("\"property\"");
assertThat(result).doesNotContain("readOnly");
assertThat(result).doesNotContain("transientProperty");
assertThat(result).doesNotContain("annotatedTransientProperty");
assertThat(jsonResult, containsString(pointTemplate("pointA", point)));
assertThat(jsonResult, containsString(pointTemplate("pointB", point)));
assertThat(jsonResult, containsString(String.format(Locale.ENGLISH, "\"%s\":\"%s\"", "pointC", pointAsString)));
assertThat(jsonResult, containsString(String.format(Locale.ENGLISH, "\"%s\":[%.1f,%.1f]", "pointD", pointAsArray[0], pointAsArray[1])));
}
private String pointTemplate(String name, Point point) {
return String.format(Locale.ENGLISH, "\"%s\":{\"lat\":%.1f,\"lon\":%.1f}", name, point.getX(), point.getY());
}
public static class Sample {
public @ReadOnlyProperty String readOnly;
public @Transient String annotatedTransientProperty;
public transient String transientProperty;
public String property;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2017 the original author or authors.
* Copyright 2013-2016 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.
@@ -15,48 +15,44 @@
*/
package org.springframework.data.elasticsearch.core;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import com.fasterxml.jackson.databind.util.ArrayIterator;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.MultiGetItemResponse;
import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.document.DocumentField;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import org.springframework.data.elasticsearch.entities.Car;
import org.springframework.data.elasticsearch.entities.SampleEntity;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.Value;
import java.util.*;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.databind.util.ArrayIterator;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHitField;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.internal.InternalSearchHitField;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.data.annotation.AccessType;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.Page;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.core.DefaultResultMapperTests.ImmutableEntity;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import org.springframework.data.elasticsearch.entities.Car;
/**
* @author Artur Konczak
* @author Mohsin Husen
* @author Chris White
* @author Mark Paluch
* @author Ilkang Na
*/
public class DefaultResultMapperTests {
@@ -76,20 +72,25 @@ public class DefaultResultMapperTests {
//Given
SearchHit[] hits = {createCarHit("Ford", "Grat"), createCarHit("BMW", "Arrow")};
SearchHits searchHits = mock(SearchHits.class);
when(searchHits.getTotalHits()).thenReturn(2L);
when(searchHits.totalHits()).thenReturn(2L);
when(searchHits.iterator()).thenReturn(new ArrayIterator(hits));
when(response.getHits()).thenReturn(searchHits);
Aggregations aggregations = new Aggregations(asList(createCarAggregation()));
Aggregation aggregationToReturn = createCarAggregation();
Aggregations aggregations = mock(Aggregations.class);
Iterator<Aggregation> iter = Collections.singletonList(aggregationToReturn).iterator();
when(aggregations.iterator()).thenReturn(iter).thenReturn(iter);
when(aggregations.get("engine")).thenReturn(aggregationToReturn);
when(response.getAggregations()).thenReturn(aggregations);
//When
AggregatedPage<Car> page = (AggregatedPage<Car>) resultMapper.mapResults(response, Car.class, Pageable.unpaged());
AggregatedPage<Car> page = (AggregatedPage<Car>) resultMapper.mapResults(response, Car.class, null);
//Then
page.hasFacets();
assertThat(page.hasAggregations(), is(true));
assertThat(page.getAggregation("Diesel").getName(), is("Diesel"));
assertThat(page.getAggregation("engine").getName(), is("Diesel"));
}
@Test
@@ -97,12 +98,12 @@ public class DefaultResultMapperTests {
//Given
SearchHit[] hits = {createCarHit("Ford", "Grat"), createCarHit("BMW", "Arrow")};
SearchHits searchHits = mock(SearchHits.class);
when(searchHits.getTotalHits()).thenReturn(2L);
when(searchHits.totalHits()).thenReturn(2L);
when(searchHits.iterator()).thenReturn(new ArrayIterator(hits));
when(response.getHits()).thenReturn(searchHits);
//When
Page<Car> page = resultMapper.mapResults(response, Car.class, Pageable.unpaged());
Page<Car> page = resultMapper.mapResults(response, Car.class, null);
//Then
assertThat(page.hasContent(), is(true));
@@ -115,12 +116,12 @@ public class DefaultResultMapperTests {
//Given
SearchHit[] hits = {createCarPartialHit("Ford", "Grat"), createCarPartialHit("BMW", "Arrow")};
SearchHits searchHits = mock(SearchHits.class);
when(searchHits.getTotalHits()).thenReturn(2L);
when(searchHits.totalHits()).thenReturn(2L);
when(searchHits.iterator()).thenReturn(new ArrayIterator(hits));
when(response.getHits()).thenReturn(searchHits);
//When
Page<Car> page = resultMapper.mapResults(response, Car.class, Pageable.unpaged());
Page<Car> page = resultMapper.mapResults(response, Car.class, null);
//Then
assertThat(page.hasContent(), is(true));
@@ -142,86 +143,23 @@ public class DefaultResultMapperTests {
assertThat(result.getModel(), is("Grat"));
assertThat(result.getName(), is("Ford"));
}
/**
* @see DATAES-281.
*/
@Test
public void setsIdentifierOnImmutableType() {
GetResponse response = mock(GetResponse.class);
when(response.getSourceAsString()).thenReturn("{}");
when(response.getId()).thenReturn("identifier");
ImmutableEntity result = resultMapper.mapResult(response, ImmutableEntity.class);
assertThat(result, is(notNullValue()));
assertThat(result.getId(), is("identifier"));
}
@Test // DATAES-198
public void setsVersionFromGetResponse() {
GetResponse response = mock(GetResponse.class);
when(response.getSourceAsString()).thenReturn("{}");
when(response.getVersion()).thenReturn(1234L);
SampleEntity result = resultMapper.mapResult(response, SampleEntity.class);
assertThat(result, is(notNullValue()));
assertThat(result.getVersion(), is(1234L));
}
@Test // DATAES-198
public void setsVersionFromMultiGetResponse() {
GetResponse response1 = mock(GetResponse.class);
when(response1.getSourceAsString()).thenReturn("{}");
when(response1.isExists()).thenReturn(true);
when(response1.getVersion()).thenReturn(1234L);
GetResponse response2 = mock(GetResponse.class);
when(response2.getSourceAsString()).thenReturn("{}");
when(response2.isExists()).thenReturn(true);
when(response2.getVersion()).thenReturn(5678L);
MultiGetResponse multiResponse = mock(MultiGetResponse.class);
when(multiResponse.getResponses()).thenReturn(new MultiGetItemResponse[] {
new MultiGetItemResponse(response1, null), new MultiGetItemResponse(response2, null) });
LinkedList<SampleEntity> results = resultMapper.mapResults(multiResponse, SampleEntity.class);
assertThat(results, is(notNullValue()));
assertThat(results, hasSize(2));
assertThat(results.get(0).getVersion(), is(1234L));
assertThat(results.get(1).getVersion(), is(5678L));
}
@Test // DATAES-198
public void setsVersionFromSearchResponse() {
SearchHit hit1 = mock(SearchHit.class);
when(hit1.getSourceAsString()).thenReturn("{}");
when(hit1.getVersion()).thenReturn(1234L);
SearchHit hit2 = mock(SearchHit.class);
when(hit2.getSourceAsString()).thenReturn("{}");
when(hit2.getVersion()).thenReturn(5678L);
SearchHits searchHits = mock(SearchHits.class);
when(searchHits.getTotalHits()).thenReturn(2L);
when(searchHits.iterator()).thenReturn(Arrays.asList(hit1, hit2).iterator());
SearchResponse searchResponse = mock(SearchResponse.class);
when(searchResponse.getHits()).thenReturn(searchHits);
AggregatedPage<SampleEntity> results = resultMapper.mapResults(searchResponse, SampleEntity.class,
mock(Pageable.class));
assertThat(results, is(notNullValue()));
assertThat(results.getContent().get(0).getVersion(), is(1234L));
assertThat(results.getContent().get(1).getVersion(), is(5678L));
}
private Aggregation createCarAggregation() {
Aggregation aggregation = mock(Terms.class);
when(aggregation.getName()).thenReturn("Diesel");
@@ -230,13 +168,13 @@ public class DefaultResultMapperTests {
private SearchHit createCarHit(String name, String model) {
SearchHit hit = mock(SearchHit.class);
when(hit.getSourceAsString()).thenReturn(createJsonCar(name, model));
when(hit.sourceAsString()).thenReturn(createJsonCar(name, model));
return hit;
}
private SearchHit createCarPartialHit(String name, String model) {
SearchHit hit = mock(SearchHit.class);
when(hit.getSourceAsString()).thenReturn(null);
when(hit.sourceAsString()).thenReturn(null);
when(hit.getFields()).thenReturn(createCarFields(name, model));
return hit;
}
@@ -249,14 +187,14 @@ public class DefaultResultMapperTests {
return sb.toString();
}
private Map<String, DocumentField> createCarFields(String name, String model) {
Map<String, DocumentField> result = new HashMap<>();
result.put("name", new DocumentField("name", asList(name)));
result.put("model", new DocumentField("model", asList(model)));
private Map<String, SearchHitField> createCarFields(String name, String model) {
Map<String, SearchHitField> result = new HashMap<String, SearchHitField>();
result.put("name", new InternalSearchHitField("name", Arrays.<Object>asList(name)));
result.put("model", new InternalSearchHitField("model", Arrays.<Object>asList(model)));
return result;
}
@Document(indexName = "test-index-immutable-internal")
@Document(indexName = "someIndex")
@NoArgsConstructor(force = true)
@Getter
static class ImmutableEntity {

Some files were not shown because too many files have changed in this diff Show More