1
0
mirror of synced 2026-05-31 00:23:16 +00:00

Compare commits

...

127 Commits

Author SHA1 Message Date
Mark Paluch a1d508c656 DATAES-448 - Release version 3.0.8 (Kay SR8). 2018-06-13 15:13:01 +02:00
Mark Paluch 04308394dd DATAES-448 - Prepare 3.0.8 (Kay SR8). 2018-06-13 15:12:06 +02:00
Mark Paluch be80d7eae4 DATAES-448 - Updated changelog. 2018-06-13 15:12:04 +02:00
Mark Paluch de1c28979d DATAES-447 - Updated changelog. 2018-06-13 15:02:00 +02:00
Oliver Gierke bd668e6c2a DATAES-460 - Avoid Netty 3 dependency.
We now use a custom TransportClient implementation that reflectively pulls in the Netty transport client plugins. The previously used PreBuiltTransportClient expects both the Netty3 and the Netty 4 variant to be available at runtime. We now explicitly exclude Netty 3 so that Spring Data Elasticsearch projects run on Netty 4 by default.

Users required to stay on Netty 3 can explicitly declared the now excluded dependency.

Related tickets: https://github.com/elastic/elasticsearch/issues/31240
2018-06-11 14:11:25 +02:00
Christoph Strobl ba899a0017 DATAES-440 - Updated changelog. 2018-05-17 10:32:58 +02:00
Ted Liang 8181c713c7 DATAES-312 - Fix NullHandling.NULLS_LAST in query.sort
Original pull request: #163
2018-05-17 09:45:10 +02:00
Nordine Bittich c6419a1f05 DATAES-420 - Analyzer of main field ignored when using @MultiField annotation 2018-05-17 09:45:04 +02:00
Mark Paluch 09ee8f9026 DATAES-437 - After release cleanups. 2018-05-08 15:04:29 +02:00
Mark Paluch 13cfb039b5 DATAES-437 - Prepare next development iteration. 2018-05-08 15:04:27 +02:00
Mark Paluch 4c9c03ac0b DATAES-437 - Release version 3.0.7 (Kay SR7). 2018-05-08 14:15:28 +02:00
Mark Paluch cd597f059e DATAES-437 - Prepare 3.0.7 (Kay SR7). 2018-05-08 14:14:33 +02:00
Mark Paluch 7cf251a24e DATAES-437 - Updated changelog. 2018-05-08 14:14:31 +02:00
Mark Paluch fe5426b870 DATAES-436 - Updated changelog. 2018-05-08 12:22:53 +02:00
xhaggi 01a37c4fc3 DATAES-437 - update version overview in README 2018-05-08 11:40:01 +02:00
xhaggi 021495580f DATAES-285 - fix broken tests after 4970783ca4 2018-05-08 10:50:37 +02:00
xhaggi 4970783ca4 DATAES-285 - Polishing
* drop superfluous class FieldIndex
* change FieldType text and keyword starting with capital letters

Original commit: 089d7746be
2018-05-08 10:15:38 +02:00
Chris White 5ac31b3d2b DATAES-198 - Fixed @Version annotation on fields. 2018-05-07 13:01:25 +02:00
xhaggi 71b2ffc128 DATAES-412 - only the last highlight field is added to SearchRequest 2018-05-07 11:44:16 +02:00
Oliver Gierke 2642836e4d DATAES-363 - Polishing.
Original pull request: #183.
2018-04-18 12:45:15 +02:00
Michael Wirth 849d7da652 DATAES-363 - Fixed CrudRepository.existsById(…) implementation.
Properly use Optional.isPresent() over a null check.

Original pull request: #183.
2018-04-18 12:45:13 +02:00
xhaggi 5e29b958e5 DATAES-438 - BACKPORT - get rid of deprecation warning because of invalid mapping for @Id
(cherry picked from commit b949daa)
2018-04-13 16:03:41 +01:00
Mark Paluch 1b1ef4b5f4 DATAES-427 - Updated changelog. 2018-04-13 15:11:31 +02:00
Artur Konczak 79636c2a29 DATAES-402 - fixed broken tests 2018-04-06 10:30:41 +02:00
Remco Zigterman 787fc897d3 DATAES-402 - fixing paging information 2018-04-06 10:30:31 +02:00
Mark Paluch 4bdaf039c2 DATAES-430 - After release cleanups. 2018-04-04 16:42:34 +02:00
Mark Paluch 35003bf942 DATAES-430 - Prepare next development iteration. 2018-04-04 16:42:32 +02:00
Mark Paluch be230f4003 DATAES-430 - Release version 3.0.6 (Kay SR6). 2018-04-04 15:53:23 +02:00
Mark Paluch 8c1821e7a6 DATAES-430 - Prepare 3.0.6 (Kay SR6). 2018-04-04 15:52:32 +02:00
Mark Paluch 72a2f9f758 DATAES-430 - Updated changelog. 2018-04-04 15:52:30 +02:00
Mark Paluch d9d3521518 DATAES-423 - Updated changelog. 2018-04-04 15:16:23 +02:00
Oliver Gierke d50ae96c5e DATAES-434 - Removed explicit declaration of Jackson library versions. 2018-03-27 19:38:04 +02:00
Mark Paluch 734a28fb03 DATAES-429 - After release cleanups. 2018-02-28 10:43:36 +01:00
Mark Paluch ac403b9198 DATAES-429 - Prepare next development iteration. 2018-02-28 10:43:34 +01:00
Mark Paluch 477c4d1dc3 DATAES-429 - Release version 3.0.5 (Kay SR5). 2018-02-28 10:14:58 +01:00
Mark Paluch 2b543ff026 DATAES-429 - Prepare 3.0.5 (Kay SR5). 2018-02-28 10:14:06 +01:00
Mark Paluch 02a3e120c2 DATAES-429 - Updated changelog. 2018-02-28 10:14:04 +01:00
Mark Paluch 92286a725d DATAES-425 - After release cleanups. 2018-02-19 20:29:08 +01:00
Mark Paluch 462288be0e DATAES-425 - Prepare next development iteration. 2018-02-19 20:29:07 +01:00
Mark Paluch b844f47795 DATAES-425 - Release version 3.0.4 (Kay SR4). 2018-02-19 19:46:54 +01:00
Mark Paluch fe488eac32 DATAES-425 - Prepare 3.0.4 (Kay SR4). 2018-02-19 19:46:05 +01:00
Mark Paluch a77b81ecb3 DATAES-425 - Updated changelog. 2018-02-19 19:46:03 +01:00
Christoph Strobl 81795f67cd DATAES-401 - Updated changelog. 2018-02-06 11:14:01 +01:00
Mark Paluch 485859ca3d DATAES-417 - After release cleanups. 2018-01-24 13:46:10 +01:00
Mark Paluch 8973d2d7eb DATAES-417 - Prepare next development iteration. 2018-01-24 13:46:09 +01:00
Mark Paluch a525a38825 DATAES-417 - Release version 3.0.3 (Kay SR3). 2018-01-24 13:21:24 +01:00
Mark Paluch b392090e61 DATAES-417 - Prepare 3.0.3 (Kay SR3). 2018-01-24 13:20:39 +01:00
Mark Paluch ca4a864f9e DATAES-417 - Updated changelog. 2018-01-24 13:20:38 +01:00
Mark Paluch 3a31030f89 DATAES-424 - Fix line endings to LF. 2018-01-24 13:09:22 +01:00
Mark Paluch 34a7900e34 DATAES-416 - Updated changelog. 2018-01-24 12:22:15 +01:00
Mark Paluch 361bc2a333 DATAES-411 - After release cleanups. 2017-11-27 16:42:55 +01:00
Mark Paluch c2c21581d8 DATAES-411 - Prepare next development iteration. 2017-11-27 16:42:53 +01:00
Mark Paluch ecf2efa6e5 DATAES-411 - Release version 3.0.2 (Kay SR2). 2017-11-27 16:12:35 +01:00
Mark Paluch 418d259fbf DATAES-411 - Prepare 3.0.2 (Kay SR2). 2017-11-27 16:11:22 +01:00
Mark Paluch 737a023b5a DATAES-411 - Updated changelog. 2017-11-27 16:11:20 +01:00
Mark Paluch cc3f578312 DATAES-404 - Updated changelog. 2017-11-27 15:58:48 +01:00
Oliver Gierke 81b21f4e6f DATAES-414 - Reduced scope of Log4j dependencies to test. 2017-11-02 18:42:30 +01:00
Oliver Gierke 552cbff6a4 DATAES-400 - After release cleanups. 2017-10-27 15:50:49 +02:00
Oliver Gierke 000eb152dc DATAES-400 - Prepare next development iteration. 2017-10-27 15:50:47 +02:00
Oliver Gierke ad55402973 DATAES-400 - Release version 3.0.1 (Kay SR1). 2017-10-27 15:25:13 +02:00
Oliver Gierke ef68623d5b DATAES-400 - Prepare 3.0.1 (Kay SR1). 2017-10-27 15:24:26 +02:00
Oliver Gierke c075f170c3 DATAES-400 - Updated changelog. 2017-10-27 15:24:22 +02:00
Oliver Gierke 02b7dde196 DATAES-410 - Adapt API changes in Property in test cases. 2017-10-27 11:24:54 +02:00
Vladimir Tsanev 51b7fa2a26 DATAES-361 - Move Log4j2 config file to test sources.
The configuration file for Log4j2 had been added to src/main/resources accidentally which caused it to be picked up by user applications, e.g. in a Spring Boot application effectively disabling Boot's auto-configuration. This file has now been moved to the test resources.

Original pull request: #191.
Related tickets: spring-projects/spring-boot#10634
2017-10-13 15:41:11 +02:00
Oliver Gierke 4e5051c57b DATAES-391 - Updated changelog. 2017-10-11 19:03:34 +02:00
Mark Paluch 31d499e6e0 DATAES-392 - After release cleanups. 2017-10-02 11:38:05 +02:00
Mark Paluch 311a06aa67 DATAES-392 - Prepare next development iteration. 2017-10-02 11:38:04 +02:00
Mark Paluch d30b41cc59 DATAES-392 - Release version 3.0 GA (Kay). 2017-10-02 11:10:23 +02:00
Mark Paluch 3fa7851544 DATAES-392 - Prepare 3.0 GA (Kay). 2017-10-02 11:09:17 +02:00
Mark Paluch e990e57b6e DATAES-392 - Updated changelog. 2017-10-02 11:09:15 +02:00
Mark Paluch a30a13dced DATAES-395 - Downgrade to CDI 1.0. 2017-09-21 14:39:22 +02:00
Mark Paluch e0d85f0c2a DATAES-397 - Added explicit automatic module name for JDK 9. 2017-09-21 14:02:37 +02:00
Mark Paluch 960263837b DATAES-395 - Polishing.
Fix line endings.
2017-09-18 15:36:39 +02:00
Mark Paluch 6dd4d28067 DATAES-395 - Upgrade to OpenWebBeans 2.0.1. 2017-09-18 15:36:20 +02:00
Oliver Gierke adf846d665 DATAES-376 - After release cleanups. 2017-09-11 17:40:22 +02:00
Oliver Gierke 8193212d5b DATAES-376 - Prepare next development iteration. 2017-09-11 17:40:19 +02:00
Oliver Gierke e529c56ced DATAES-376 - Release version 3.0 RC3 (Kay). 2017-09-11 17:24:46 +02:00
Oliver Gierke 7ba5195c6e DATAES-376 - Prepare 3.0 RC3 (Kay). 2017-09-11 17:23:52 +02:00
Oliver Gierke f899cf389f DATAES-376 - Updated changelog. 2017-09-11 17:23:49 +02:00
Mark Paluch 196ab5b5e2 DATAES-378 - Updated changelog. 2017-09-11 12:44:07 +02:00
Oliver Gierke 771e01189e DATAES-374 - Updated changelog. 2017-07-27 00:49:04 +02:00
Mohsin Husen 54d1b2f3dd DATAES-375 - update README 2017-07-26 11:58:24 +01:00
Oliver Gierke 527d594389 DATAES-375 - After release cleanups. 2017-07-25 16:10:39 +02:00
Oliver Gierke 8d0e1df742 DATAES-375 - Prepare next development iteration. 2017-07-25 16:10:36 +02:00
Oliver Gierke 0767bf2c29 DATAES-375 - Release version 3.0 RC2 (Kay). 2017-07-25 15:34:24 +02:00
Oliver Gierke d16c598483 DATAES-375 - Prepare 3.0 RC2 (Kay). 2017-07-25 15:33:34 +02:00
Oliver Gierke 1adb70a72e DATAES-375 - Updated changelog. 2017-07-25 15:33:30 +02:00
Mohsin Husen 8df14e5868 DATAES-359 - Update release version in README 2017-07-25 12:32:37 +01:00
Oliver Gierke 03b686dc5d DATAES-359 - After release cleanups. 2017-07-25 10:00:09 +02:00
Oliver Gierke 90a7d05641 DATAES-359 - Prepare next development iteration. 2017-07-25 10:00:06 +02:00
Oliver Gierke 20ab332374 DATAES-359 - Release version 3.0 RC1 (Kay). 2017-07-25 09:48:50 +02:00
Oliver Gierke 3b4e719a72 DATAES-359 - Prepare 3.0 RC1 (Kay). 2017-07-25 09:48:02 +02:00
Oliver Gierke 82d779a9b9 DATAES-359 - Updated changelog. 2017-07-25 09:47:59 +02:00
Oliver Gierke 465f5d2bda DATAES-358 - Updated changelog. 2017-07-24 22:20:46 +02:00
Mohsin Husen 64def6798f DATAES-353 - Update release version in README 2017-07-24 12:35:39 +01:00
Artur Konczak 8dfee0a437 DATAES-373 - bump elasticsearch version to 5.5.0 2017-07-21 15:34:39 +01:00
Mohsin Husen ffdc573caf DATAES-353 - Update release version in README 2017-07-21 10:55:26 +01:00
Mohsin Husen a085c064d5 DATAES-274 - prevent NPE in FacetedPageImpl 2017-07-21 10:40:11 +01:00
Mohsin Husen a343bf7109 DATAES-353 - Polishing 2017-07-21 10:39:03 +01:00
Mark Paluch 7dba0441bb DATAES-369 - Polishing.
Fix linebreaks.
2017-07-04 14:36:26 +02:00
Mark Paluch b5bab6b85e DATAES-369 - Adapt to API changes in mapping subsystem. 2017-07-04 14:36:13 +02:00
Mark Paluch 4219973b84 DATAES-353 - After release cleanups. 2017-06-14 17:14:08 +02:00
Mark Paluch 5c7aba46a5 DATAES-353 - Prepare next development iteration. 2017-06-14 17:14:07 +02:00
Mark Paluch 84f9684fed DATAES-353 - Release version 3.0 M4 (Kay). 2017-06-14 17:03:48 +02:00
Mark Paluch eb62540288 DATAES-353 - Prepare 3.0 M4 (Kay). 2017-06-14 17:03:00 +02:00
Mark Paluch 29cf2893cd DATAES-353 - Updated changelog. 2017-06-14 17:02:59 +02:00
Mark Paluch 84842188d2 DATAES-349 - Updated changelog. 2017-06-08 11:56:20 +02:00
Mark Paluch d0c562dc7b DATAES-348 - Updated changelog. 2017-06-07 12:23:37 +02:00
Mohsin Husen 3d9946ac0b DATAES-285 - update readme 2017-05-31 20:11:25 +01:00
Mohsin Husen f1eb8a5eca DATAES-285 - bump elasticsearch version to 5.4.0 2017-05-31 19:49:26 +01:00
Mohsin Husen 65317ab54e DATAES-334 - Update JIRA and Forum Links in README.md 2017-05-31 19:49:26 +01:00
Artur Konczak 089d7746be DATAES-285 - upgrade to elasticsearch 5.x 2017-05-31 19:49:11 +01:00
Mark Paluch 17603ca8a9 DATAES-344 - After release cleanups. 2017-05-09 11:34:42 +02:00
Mark Paluch c8eb4ba562 DATAES-344 - Prepare next development iteration. 2017-05-09 11:34:41 +02:00
Mark Paluch 5320e9fd04 DATAES-344 - Release version 3.0 M3 (Kay). 2017-05-09 11:23:01 +02:00
Mark Paluch 1497261bc0 DATAES-344 - Prepare 3.0 M3 (Kay). 2017-05-09 11:22:12 +02:00
Mark Paluch bbf6f40eb3 DATAES-344 - Updated changelog. 2017-05-09 11:22:10 +02:00
Christoph Strobl 416a3f2baf DATAES-352 - Adapt to API changes in repository interfaces.
We now follow a more consistent naming scheme for the methods in repository that are driven by the following guidelines:

* Methods referring to an identifier now all end on …ById(…).
* Methods taking or returning a collection are named …All(…)

Please see DATACMNS-944 for details.
2017-05-05 00:03:25 +02:00
Mark Paluch 939c0f96f4 DATAES-350 - Polishing.
Use repository lookup for parent pom.
2017-04-24 10:34:30 +02:00
Mark Paluch 312df33c31 DATAES-350 - Adapt to SimpleTypeHolder changes in Spring Data Commons.
Replace constructor usage with singleton instance.

Related Ticket: DATAES-350.
2017-04-24 10:33:45 +02:00
Oliver Gierke 05a0186d1e DATAES-347 - Updated changelog. 2017-04-19 21:04:25 +02:00
Oliver Gierke 5182dabd88 DATAES-346 - Updated changelog. 2017-04-19 20:01:50 +02:00
Oliver Gierke 14ee378eea DATAES-336 - Updated changelog. 2017-04-19 13:04:12 +02:00
Oliver Gierke 53b6444c9d DATAES-335 - Updated changelog. 2017-04-19 11:50:51 +02:00
Oliver Gierke e15d894232 DATAES-326 - Updated changelog. 2017-04-10 14:31:44 +02:00
Oliver Gierke 4bb7f894ee DATAES-311 - After release cleanups. 2017-04-04 22:08:19 +02:00
Oliver Gierke 8f0df67532 DATAES-311 - Prepare next development iteration. 2017-04-04 22:08:16 +02:00
187 changed files with 14734 additions and 14489 deletions
+18 -21
View File
@@ -1,21 +1,18 @@
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
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
+8 -11
View File
@@ -52,15 +52,12 @@ the appropriate dependency version.
</repository>
```
| 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 |
| spring data elasticsearch | elasticsearch |
|:-------------------------:|:-------------:|
| 3.0.x | 5.5.0 |
| 2.1.x | 2.4.0 |
| 2.0.x | 2.2.0 |
| 1.3.x | 1.5.2 |
### ElasticsearchRepository
@@ -240,8 +237,8 @@ Using Transport Client
Here are some ways for you to get involved in the community:
* 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.
* 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.
* 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
+61 -10
View File
@@ -4,13 +4,12 @@
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>3.0.0.M2</version>
<version>3.0.8.RELEASE</version>
<parent>
<groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId>
<version>2.0.0.M2</version>
<relativePath>../spring-data-build/parent/pom.xml</relativePath>
<version>2.0.8.RELEASE</version>
</parent>
<name>Spring Data Elasticsearch</name>
@@ -20,8 +19,10 @@
<properties>
<commonscollections>3.2.1</commonscollections>
<commonslang>2.6</commonslang>
<elasticsearch>2.4.0</elasticsearch>
<springdata.commons>2.0.0.M2</springdata.commons>
<elasticsearch>5.5.0</elasticsearch>
<log4j>2.8.2</log4j>
<springdata.commons>2.0.8.RELEASE</springdata.commons>
<java-module-name>spring.data.elasticsearch</java-module-name>
</properties>
<dependencies>
@@ -71,16 +72,50 @@
<version>${elasticsearch}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>${elasticsearch}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
<exclusion>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>transport-netty3-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>transport-netty4-client</artifactId>
<version>${elasticsearch}</version>
</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 -->
@@ -97,11 +132,18 @@
<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>${webbeans}</version>
<version>1.2.8</version>
<scope>test</scope>
<exclusions>
<exclusion>
@@ -114,6 +156,15 @@
</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>
@@ -172,8 +223,8 @@
<repositories>
<repository>
<id>spring-libs-milestone</id>
<url>https://repo.spring.io/libs-milestone</url>
<id>spring-libs-release</id>
<url>https://repo.spring.io/libs-release</url>
</repository>
</repositories>
@@ -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,8 +32,6 @@ 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,56 +1,58 @@
/*
* 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;
}
/*
* 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;
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[] ignoreFields() default {};
boolean includeInParent() default false;
}
@@ -1,26 +0,0 @@
/*
* 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.
* 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;
/**
* @author Artur Konczak
* @author Mohsin Husen
* @author Alexander Volz
* @author Dennis Maaß
*/
public enum FieldIndex {
not_analyzed, analyzed, no
}
@@ -21,5 +21,17 @@ package org.springframework.data.elasticsearch.annotations;
* @author Artur Konczak
*/
public enum FieldType {
String, Integer, Long, Date, Float, Double, Boolean, Object, Auto, Nested, Ip, Attachment
Text,
Integer,
Long,
Date,
Float,
Double,
Boolean,
Object,
Auto,
Nested,
Ip,
Attachment,
Keyword
}
@@ -25,8 +25,4 @@ import java.lang.annotation.*;
@Documented
public @interface GeoPointField {
boolean geoHashPrefix() default false;
String geoHashPrecision() default "0";
}
@@ -31,11 +31,17 @@ public @interface InnerField {
FieldType type();
FieldIndex index() default FieldIndex.analyzed;
boolean index() default true;
DateFormat format() default DateFormat.none;
String pattern() default "";
boolean store() default false;
boolean fielddata() default false;
String searchAnalyzer() default "";
String indexAnalyzer() default "";
String analyzer() 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,127 +1,144 @@
/*
* 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);
}
}
}
/*
* 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.apache.commons.lang.StringUtils;
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 static java.util.Arrays.*;
/**
* NodeClientFactoryBean
*
* @author Rizwan Idrees
* @author Mohsin Husen
*/
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("transport.type", "local")
.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)
.put("script.inline", "true")
.build(), asList(Netty4Plugin.class)).start().client();
}
private Settings loadConfig() throws IOException {
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);
}
}
}
@@ -1,154 +1,267 @@
/*
* 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.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.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.util.Assert;
/**
* TransportClientFactoryBean
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Jakub Vavrik
* @author Piotr Betkier
*/
public class TransportClientFactoryBean implements FactoryBean<TransportClient>, InitializingBean, DisposableBean {
private static final Logger logger = LoggerFactory.getLogger(TransportClientFactoryBean.class);
private String clusterNodes = "127.0.0.1:9300";
private String clusterName = "elasticsearch";
private Boolean clientTransportSniff = true;
private Boolean clientIgnoreClusterName = Boolean.FALSE;
private String clientPingTimeout = "5s";
private String clientNodesSamplerInterval = "5s";
private TransportClient client;
private Properties properties;
static final String COLON = ":";
static final String COMMA = ",";
@Override
public void destroy() throws Exception {
try {
logger.info("Closing elasticSearch client");
if (client != null) {
client.close();
}
} catch (final Exception e) {
logger.error("Error closing ElasticSearch client: ", e);
}
}
@Override
public TransportClient getObject() throws Exception {
return client;
}
@Override
public Class<TransportClient> getObjectType() {
return TransportClient.class;
}
@Override
public boolean isSingleton() {
return false;
}
@Override
public void afterPropertiesSet() throws Exception {
buildClient();
}
protected void buildClient() throws Exception {
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) {
return Settings.builder().put(properties).build();
}
return Settings.builder()
.put("cluster.name", clusterName)
.put("client.transport.sniff", clientTransportSniff)
.put("client.transport.ignore_cluster_name", clientIgnoreClusterName)
.put("client.transport.ping_timeout", clientPingTimeout)
.put("client.transport.nodes_sampler_interval", clientNodesSamplerInterval)
.build();
}
public void setClusterNodes(String clusterNodes) {
this.clusterNodes = clusterNodes;
}
public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
public void setClientTransportSniff(Boolean clientTransportSniff) {
this.clientTransportSniff = clientTransportSniff;
}
public String getClientNodesSamplerInterval() {
return clientNodesSamplerInterval;
}
public void setClientNodesSamplerInterval(String clientNodesSamplerInterval) {
this.clientNodesSamplerInterval = clientNodesSamplerInterval;
}
public String getClientPingTimeout() {
return clientPingTimeout;
}
public void setClientPingTimeout(String clientPingTimeout) {
this.clientPingTimeout = clientPingTimeout;
}
public Boolean getClientIgnoreClusterName() {
return clientIgnoreClusterName;
}
public void setClientIgnoreClusterName(Boolean clientIgnoreClusterName) {
this.clientIgnoreClusterName = clientIgnoreClusterName;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
}
/*
* 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.client;
import static org.apache.commons.lang.StringUtils.*;
import io.netty.util.ThreadDeathWatcher;
import io.netty.util.concurrent.GlobalEventExecutor;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.index.reindex.ReindexPlugin;
import org.elasticsearch.join.ParentJoinPlugin;
import org.elasticsearch.percolator.PercolatorPlugin;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.mustache.MustachePlugin;
import org.elasticsearch.transport.Netty4Plugin;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
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.Assert;
import org.springframework.util.ClassUtils;
/**
* TransportClientFactoryBean
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Jakub Vavrik
* @author Piotr Betkier
*/
public class TransportClientFactoryBean implements FactoryBean<TransportClient>, InitializingBean, DisposableBean {
private static final Logger logger = LoggerFactory.getLogger(TransportClientFactoryBean.class);
private String clusterNodes = "127.0.0.1:9300";
private String clusterName = "elasticsearch";
private Boolean clientTransportSniff = true;
private Boolean clientIgnoreClusterName = Boolean.FALSE;
private String clientPingTimeout = "5s";
private String clientNodesSamplerInterval = "5s";
private TransportClient client;
private Properties properties;
static final String COLON = ":";
static final String COMMA = ",";
@Override
public void destroy() throws Exception {
try {
logger.info("Closing elasticSearch client");
if (client != null) {
client.close();
}
} catch (final Exception e) {
logger.error("Error closing ElasticSearch client: ", e);
}
}
@Override
public TransportClient getObject() throws Exception {
return client;
}
@Override
public Class<TransportClient> getObjectType() {
return TransportClient.class;
}
@Override
public boolean isSingleton() {
return false;
}
@Override
public void afterPropertiesSet() throws Exception {
buildClient();
}
protected void buildClient() throws Exception {
client = new SpringDataTransportClient(settings());
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) {
return Settings.builder().put(properties).build();
}
return Settings.builder()
.put("cluster.name", clusterName)
.put("client.transport.sniff", clientTransportSniff)
.put("client.transport.ignore_cluster_name", clientIgnoreClusterName)
.put("client.transport.ping_timeout", clientPingTimeout)
.put("client.transport.nodes_sampler_interval", clientNodesSamplerInterval)
.build();
}
public void setClusterNodes(String clusterNodes) {
this.clusterNodes = clusterNodes;
}
public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
public void setClientTransportSniff(Boolean clientTransportSniff) {
this.clientTransportSniff = clientTransportSniff;
}
public String getClientNodesSamplerInterval() {
return clientNodesSamplerInterval;
}
public void setClientNodesSamplerInterval(String clientNodesSamplerInterval) {
this.clientNodesSamplerInterval = clientNodesSamplerInterval;
}
public String getClientPingTimeout() {
return clientPingTimeout;
}
public void setClientPingTimeout(String clientPingTimeout) {
this.clientPingTimeout = clientPingTimeout;
}
public Boolean getClientIgnoreClusterName() {
return clientIgnoreClusterName;
}
public void setClientIgnoreClusterName(Boolean clientIgnoreClusterName) {
this.clientIgnoreClusterName = clientIgnoreClusterName;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
/**
* Pretty exact copy of {@link PreBuiltTransportClient} except that we're inspecting the classpath for Netty
* dependencies to only include the ones available. {@link PreBuiltTransportClient} expects both Netty 3 and Netty 4
* to be present.
*
* @author Oliver Gierke
* @see https://github.com/elastic/elasticsearch/issues/31240
*/
@SuppressWarnings("unchecked")
private static class SpringDataTransportClient extends TransportClient {
/**
* Netty wants to do some unwelcome things like use unsafe and replace a private field, or use a poorly considered
* buffer recycler. This method disables these things by default, but can be overridden by setting the corresponding
* system properties.
*/
private static void initializeNetty() {
/*
* We disable three pieces of Netty functionality here:
* - we disable Netty from being unsafe
* - we disable Netty from replacing the selector key set
* - we disable Netty from using the recycler
*
* While permissions are needed to read and set these, the permissions needed here are innocuous and thus should simply be granted
* rather than us handling a security exception here.
*/
setSystemPropertyIfUnset("io.netty.noUnsafe", Boolean.toString(true));
setSystemPropertyIfUnset("io.netty.noKeySetOptimization", Boolean.toString(true));
setSystemPropertyIfUnset("io.netty.recycler.maxCapacityPerThread", Integer.toString(0));
}
@SuppressForbidden(reason = "set system properties to configure Netty")
private static void setSystemPropertyIfUnset(final String key, final String value) {
final String currentValue = System.getProperty(key);
if (currentValue == null) {
System.setProperty(key, value);
}
}
private static final List<String> OPTIONAL_DEPENDENCIES = Arrays.asList( //
"org.elasticsearch.transport.Netty3Plugin", //
"org.elasticsearch.transport.Netty4Plugin");
private static final Collection<Class<? extends Plugin>> PRE_INSTALLED_PLUGINS;
static {
initializeNetty();
List<Class<? extends Plugin>> plugins = new ArrayList<>();
boolean found = false;
for (String dependency : OPTIONAL_DEPENDENCIES) {
try {
plugins.add((Class<? extends Plugin>) ClassUtils.forName(dependency,
SpringDataTransportClient.class.getClassLoader()));
found = true;
} catch (ClassNotFoundException | LinkageError e) {}
}
Assert.state(found, "Neither Netty 3 or Netty 4 plugin found on the classpath. One of them is required to run the transport client!");
plugins.add(ReindexPlugin.class);
plugins.add(PercolatorPlugin.class);
plugins.add(MustachePlugin.class);
plugins.add(ParentJoinPlugin.class);
PRE_INSTALLED_PLUGINS = Collections.unmodifiableList(plugins);
}
public SpringDataTransportClient(Settings settings) {
super(settings, PRE_INSTALLED_PLUGINS);
}
@Override
public void close() {
super.close();
if (NetworkModule.TRANSPORT_TYPE_SETTING.exists(settings) == false
|| NetworkModule.TRANSPORT_TYPE_SETTING.get(settings).equals(Netty4Plugin.NETTY_TRANSPORT_NAME)) {
try {
GlobalEventExecutor.INSTANCE.awaitInactivity(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
try {
ThreadDeathWatcher.awaitInactivity(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
}
@@ -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;
}
}
@@ -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 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");
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");
StringBuilder dist = new StringBuilder();
@@ -129,15 +129,15 @@ class CriteriaFilterProcessor {
if (valArray[0] instanceof GeoPoint) {
GeoPoint loc = (GeoPoint) valArray[0];
geoDistanceQueryBuilder.lat(loc.getLat()).lon(loc.getLon()).distance(dist.toString()).geoDistance(GeoDistance.PLANE);
geoDistanceQueryBuilder.point(loc.getLat(),loc.getLon()).distance(dist.toString()).geoDistance(GeoDistance.PLANE);
} else if (valArray[0] instanceof Point) {
GeoPoint loc = GeoPoint.fromPoint((Point) valArray[0]);
geoDistanceQueryBuilder.lat(loc.getLat()).lon(loc.getLon()).distance(dist.toString()).geoDistance(GeoDistance.PLANE);
geoDistanceQueryBuilder.point(loc.getLat(), loc.getLon()).distance(dist.toString()).geoDistance(GeoDistance.PLANE);
} else {
String loc = (String) valArray[0];
if (loc.contains(",")) {
String c[] = loc.split(",");
geoDistanceQueryBuilder.lat(Double.parseDouble(c[0])).lon(Double.parseDouble(c[1])).distance(dist.toString()).geoDistance(GeoDistance.PLANE);
geoDistanceQueryBuilder.point(Double.parseDouble(c[0]), 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 String
//2x text
twoParameterBBox((GeoBoundingBoxQueryBuilder) filter, valArray);
} else {
//error
@@ -206,8 +206,7 @@ class CriteriaFilterProcessor {
geoBBox = (GeoBox) value;
}
filter.topLeft(geoBBox.getTopLeft().getLat(), geoBBox.getTopLeft().getLon());
filter.bottomRight(geoBBox.getBottomRight().getLat(), geoBBox.getBottomRight().getLon());
filter.setCorners(geoBBox.getTopLeft().getLat(), geoBBox.getTopLeft().getLon(), geoBBox.getBottomRight().getLat(), geoBBox.getBottomRight().getLon());
}
private static boolean isType(Object[] array, Class clazz) {
@@ -220,17 +219,15 @@ 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 String(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 text(format lat,lon or geohash)");
if (values[0] instanceof GeoPoint) {
GeoPoint topLeft = (GeoPoint) values[0];
GeoPoint bottomRight = (GeoPoint) values[1];
filter.topLeft(topLeft.getLat(), topLeft.getLon());
filter.bottomRight(bottomRight.getLat(), bottomRight.getLon());
filter.setCorners(topLeft.getLat(), topLeft.getLon(), bottomRight.getLat(), bottomRight.getLon());
} else {
String topLeft = (String) values[0];
String bottomRight = (String) values[1];
filter.topLeft(topLeft);
filter.bottomRight(bottomRight);
filter.setCorners(topLeft, bottomRight);
}
}
@@ -1,210 +1,206 @@
/*
* 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.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<>();
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(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);
}
}
}
/*
* 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);
}
}
@@ -22,7 +22,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.get.GetResponse;
@@ -40,6 +39,7 @@ import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPa
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.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonFactory;
@@ -50,6 +50,7 @@ import com.fasterxml.jackson.core.JsonGenerator;
* @author Petar Tahchiev
* @author Young Gu
* @author Oliver Gierke
* @author Chris White
* @author Mark Paluch
*/
public class DefaultResultMapper extends AbstractResultMapper {
@@ -89,12 +90,13 @@ public class DefaultResultMapper extends AbstractResultMapper {
result = mapEntity(hit.getFields().values(), clazz);
}
setPersistentEntityId(result, hit.getId(), clazz);
setPersistentEntityVersion(result, hit.getVersion(), clazz);
populateScriptFields(result, hit);
results.add(result);
}
}
return new AggregatedPageImpl<>(results, pageable, totalHits, response.getAggregations());
return new AggregatedPageImpl<T>(results, pageable, totalHits, response.getAggregations(), response.getScrollId());
}
private <T> void populateScriptFields(T result, SearchHit hit) {
@@ -154,6 +156,7 @@ 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;
}
@@ -165,6 +168,7 @@ public class DefaultResultMapper extends AbstractResultMapper {
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);
}
}
@@ -176,16 +180,29 @@ public class DefaultResultMapper extends AbstractResultMapper {
if (mappingContext != null && clazz.isAnnotationPresent(Document.class)) {
ElasticsearchPersistentEntity<?> persistentEntity = mappingContext.getRequiredPersistentEntity(clazz);
Optional<ElasticsearchPersistentProperty> idProperty = persistentEntity.getIdProperty();
ElasticsearchPersistentProperty idProperty = persistentEntity.getIdProperty();
// Only deal with String because ES generated Ids are strings !
idProperty.ifPresent(property -> {
if (property.getType().isAssignableFrom(String.class)) {
persistentEntity.getPropertyAccessor(result).setProperty(property, Optional.ofNullable(id));
}
});
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 (mappingContext != null && 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);
}
}
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -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,7 +33,14 @@ 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.*;
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;
/**
* Container for query result and facet results
@@ -42,6 +49,8 @@ import org.springframework.data.elasticsearch.core.facet.result.*;
* @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> {
@@ -54,7 +63,7 @@ public abstract class FacetedPageImpl<T> extends PageImpl<T> implements FacetedP
}
public FacetedPageImpl(List<T> content, Pageable pageable, long total) {
super(content, pageable, total);
super(content, ofNullable(pageable).orElse(Pageable.unpaged()), total);
}
@Override
@@ -84,47 +93,76 @@ public abstract class FacetedPageImpl<T> extends PageImpl<T> implements FacetedP
* Lazy conversion from aggregation to old facets
*/
private void processAggregations() {
if (facets == null) {
facets = new ArrayList<>();
for (Aggregation agg : getAggregations()) {
if (agg instanceof Terms) {
List<Term> terms = new ArrayList<>();
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<>();
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<>();
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));
}
}
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));
}
}
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,369 +1,381 @@
/*
* 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 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.ResolvableType;
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
* @author Mark Paluch
*/
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<>();
// 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) {
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-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 static org.apache.commons.lang.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_PROPERTIES = "properties";
public static final String FIELD_PARENT = "_parent";
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, 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<>();
// 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 (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_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;
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();
} 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();
} 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 (isNotBlank(analyzer)) {
builder.field(FIELD_INDEX_ANALYZER, analyzer);
}
if (isNotBlank(searchAnalyzer)) {
builder.field(FIELD_SEARCH_ANALYZER, searchAnalyzer);
}
}
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;
}
}
@@ -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();
}
@@ -0,0 +1,13 @@
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,11 +3,12 @@ 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.ScrolledPage;
/**
* @author Petar Tahchiev
*/
public interface AggregatedPage<T> extends FacetedPage<T> {
public interface AggregatedPage<T> extends FacetedPage<T>, ScrolledPage<T> {
boolean hasAggregations();
@@ -34,15 +34,26 @@ public class AggregatedPageImpl<T> extends FacetedPageImpl<T> implements Aggrega
private Aggregations aggregations;
private Map<String, Aggregation> mapOfAggregations = new HashMap<>();
private String scrollId;
public AggregatedPageImpl(List<T> content) {
super(content);
}
public AggregatedPageImpl(List<T> content, String scrollId) {
super(content);
this.scrollId = scrollId;
}
public AggregatedPageImpl(List<T> content, Pageable pageable, long total) {
super(content, pageable, total);
}
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, Aggregations aggregations) {
super(content, pageable, total);
this.aggregations = aggregations;
@@ -53,6 +64,17 @@ public class AggregatedPageImpl<T> extends FacetedPageImpl<T> implements Aggrega
}
}
public AggregatedPageImpl(List<T> content, Pageable pageable, long total, Aggregations aggregations, String scrollId) {
super(content, pageable, total);
this.aggregations = aggregations;
this.scrollId = scrollId;
if (aggregations != null) {
for (Aggregation aggregation : aggregations) {
mapOfAggregations.put(aggregation.getName(), aggregation);
}
}
}
@Override
public boolean hasAggregations() {
return aggregations != null && mapOfAggregations.size() > 0;
@@ -67,4 +89,9 @@ 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;
}
}
@@ -11,9 +11,7 @@ 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
@@ -31,22 +29,6 @@ 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);
}
}
}
@@ -19,7 +19,7 @@ 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.DateHistogramBuilder;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
import org.springframework.util.Assert;
@@ -57,16 +57,16 @@ public class HistogramFacetRequest extends AbstractFacetRequest {
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 !!!");
DateHistogramBuilder dateHistogramBuilder = AggregationBuilders.dateHistogram(getName());
DateHistogramAggregationBuilder dateHistogramBuilder = AggregationBuilders.dateHistogram(getName());
dateHistogramBuilder.field(field);
if (timeUnit != null) {
dateHistogramBuilder.interval(timeUnit);
dateHistogramBuilder.dateHistogramInterval(timeUnit);
} else {
dateHistogramBuilder.interval(interval);
}
dateHistogramBuilder.subAggregation(AggregationBuilders.extendedStats(INTERNAL_STATS));
dateHistogramBuilder.subAggregation(AggregationBuilders.extendedStats(INTERNAL_STATS).field(field));
return dateHistogramBuilder;
}
@@ -22,7 +22,7 @@ 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.RangeBuilder;
import org.elasticsearch.search.aggregations.bucket.range.RangeAggregationBuilder;
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
import org.springframework.util.Assert;
@@ -76,15 +76,16 @@ public class RangeFacetRequest extends AbstractFacetRequest {
public AbstractAggregationBuilder getFacet() {
Assert.notNull(getName(), "Facet name can't be a null !!!");
RangeBuilder rangeBuilder = AggregationBuilders.range(getName());
rangeBuilder.field(StringUtils.isNotBlank(keyField) ? keyField : field );
RangeAggregationBuilder rangeBuilder = AggregationBuilders.range(getName());
final String field = StringUtils.isNotBlank(keyField) ? keyField : this.field;
rangeBuilder.field(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));
rangeBuilder.subAggregation(AggregationBuilders.extendedStats(INTERNAL_STATS).field(field));
if(StringUtils.isNotBlank(valueField)){
rangeBuilder.subAggregation(AggregationBuilders.sum(RANGE_INTERNAL_SUM).field(valueField));
}
@@ -18,10 +18,12 @@ package org.springframework.data.elasticsearch.core.facet.request;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.lucene.util.automaton.RegExp;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsBuilder;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.terms.support.IncludeExclude;
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
import org.springframework.util.Assert;
@@ -75,7 +77,7 @@ public class TermFacetRequest extends AbstractFacetRequest {
@Override
public AbstractAggregationBuilder getFacet() {
Assert.notEmpty(fields, "Please select at last one field !!!");
TermsBuilder termsBuilder = AggregationBuilders.terms(getName()).field(fields[0]).size(this.size);
final TermsAggregationBuilder termsBuilder = AggregationBuilders.terms(getName()).field(fields[0]).size(this.size);
switch (order) {
case descTerm:
@@ -91,7 +93,7 @@ public class TermFacetRequest extends AbstractFacetRequest {
termsBuilder.order(Terms.Order.count(true));
}
if (ArrayUtils.isNotEmpty(excludeTerms)) {
termsBuilder.exclude(excludeTerms);
termsBuilder.includeExclude(new IncludeExclude(null,excludeTerms));
}
if (allTerms) {
@@ -99,7 +101,7 @@ public class TermFacetRequest extends AbstractFacetRequest {
}
if (StringUtils.isNotBlank(regex)) {
termsBuilder.include(regex);
termsBuilder.includeExclude(new IncludeExclude(new RegExp(regex),null));
}
return termsBuilder;
@@ -1,10 +1,8 @@
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;
@@ -32,39 +30,15 @@ public class CustomGeoModule extends SimpleModule {
}
class PointSerializer extends JsonSerializer<Point> {
@Override
public void serialize(Point value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
public void serialize(Point value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
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, 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);
public Point deserialize(JsonParser p, DeserializationContext context) throws IOException {
return GeoPoint.toPoint(p.readValueAs(GeoPoint.class));
}
}
@@ -1,54 +1,52 @@
/*
* 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 java.util.Optional;
import org.springframework.data.mapping.PersistentEntity;
/**
* ElasticsearchPersistentEntity
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Mark Paluch
*/
public interface ElasticsearchPersistentEntity<T> extends PersistentEntity<T, ElasticsearchPersistentProperty> {
String getIndexName();
String getIndexType();
short getShards();
short getReplicas();
boolean isUseServerConfiguration();
String getRefreshInterval();
String getIndexStoreType();
Optional<ElasticsearchPersistentProperty> getVersionProperty();
Optional<String> getParentType();
Optional<ElasticsearchPersistentProperty> getParentIdProperty();
String settingPath();
boolean isCreateIndexAndMapping();
}
/*
* 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.data.mapping.PersistentEntity;
/**
* ElasticsearchPersistentEntity
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Mark Paluch
*/
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,40 +1,40 @@
/*
* 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();
}
}
}
/*
* 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,58 @@
/*
* 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-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;
}
}
@@ -1,171 +1,171 @@
/*
* 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 java.util.Optional;
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
* @author Mark Paluch
*/
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 Optional<String> parentType = Optional.empty();
private Optional<ElasticsearchPersistentProperty> parentIdProperty = Optional.empty();
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 Optional<String> getParentType() {
return parentType;
}
@Override
public Optional<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);
Optional<Parent> annotation = property.findAnnotation(Parent.class);
annotation.ifPresent(parent -> {
Assert.isTrue(!this.parentIdProperty.isPresent(), "Only one field can hold a @Parent annotation");
Assert.isTrue(!this.parentType.isPresent(), "Only one field can hold a @Parent annotation");
Assert.isTrue(property.getType() == String.class, "Parent ID property should be String");
this.parentIdProperty = Optional.of(property);
this.parentType = Optional.of(parent.type());
});
if (property.isVersionProperty()) {
Assert.isTrue(property.getType() == Long.class, "Version property should be Long");
}
}
}
/*
* 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 java.util.Optional;
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
* @author Mark Paluch
*/
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);
Parent annotation = property.findAnnotation(Parent.class);
if (annotation != 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 = annotation.type();
}
if (property.isVersionProperty()) {
Assert.isTrue(property.getType() == Long.class, "Version property should be Long");
}
}
}
@@ -1,65 +1,65 @@
/*
* 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 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.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
*/
public class SimpleElasticsearchPersistentProperty extends
AnnotationBasedPersistentProperty<ElasticsearchPersistentProperty> implements ElasticsearchPersistentProperty {
private static final Set<Class<?>> SUPPORTED_ID_TYPES = new HashSet<>();
private static final Set<String> SUPPORTED_ID_PROPERTY_NAMES = new HashSet<>();
static {
SUPPORTED_ID_TYPES.add(String.class);
SUPPORTED_ID_PROPERTY_NAMES.add("id");
SUPPORTED_ID_PROPERTY_NAMES.add("documentId");
}
public SimpleElasticsearchPersistentProperty(Property property,
PersistentEntity<?, ElasticsearchPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
super(property, owner, simpleTypeHolder);
}
@Override
public String getFieldName() {
return getProperty().getName();
}
@Override
public boolean isIdProperty() {
return super.isIdProperty() || SUPPORTED_ID_PROPERTY_NAMES.contains(getFieldName());
}
@Override
protected Association<ElasticsearchPersistentProperty> createAssociation() {
return null;
}
}
/*
* 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 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.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
*/
public class SimpleElasticsearchPersistentProperty extends
AnnotationBasedPersistentProperty<ElasticsearchPersistentProperty> implements ElasticsearchPersistentProperty {
private static final Set<Class<?>> SUPPORTED_ID_TYPES = new HashSet<>();
private static final Set<String> SUPPORTED_ID_PROPERTY_NAMES = new HashSet<>();
static {
SUPPORTED_ID_TYPES.add(String.class);
SUPPORTED_ID_PROPERTY_NAMES.add("id");
SUPPORTED_ID_PROPERTY_NAMES.add("documentId");
}
public SimpleElasticsearchPersistentProperty(Property property,
PersistentEntity<?, ElasticsearchPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
super(property, owner, simpleTypeHolder);
}
@Override
public String getFieldName() {
return getProperty().getName();
}
@Override
public boolean isIdProperty() {
return super.isIdProperty() || SUPPORTED_ID_PROPERTY_NAMES.contains(getFieldName());
}
@Override
protected Association<ElasticsearchPersistentProperty> createAssociation() {
return null;
}
}
@@ -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,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.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-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;
}
}
@@ -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,187 @@
/*
* 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-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;
}
}
@@ -1,140 +1,140 @@
/*
* 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 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<>();
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<>();
}
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-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 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
*/
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.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<>();
}
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;
}
}
@@ -1,197 +1,197 @@
/*
* 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 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
* @author Mark Paluch
*/
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.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 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);
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;
}
}
/*
* 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 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.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
*/
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.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 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);
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,158 +1,150 @@
/*
* 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 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
* @author Mark Paluch
*/
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 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();
}
/*
* 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 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
* @author Mark Paluch
*/
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 Ids
*
* @return
*/
Collection<String> getIds();
/**
* Get route
*
* @return
*/
String getRoute();
/**
* Type of search
*
* @return
*/
SearchType getSearchType();
}
@@ -1,52 +1,52 @@
/*
* 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();
}
/*
* 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.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
*/
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,87 +1,87 @@
/*
* 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.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, java.util.Optional)
*/
@Override
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType,
Optional<Object> customImplementation) {
ElasticsearchOperations elasticsearchOperations = getDependencyInstance(elasticsearchOperationsBean,
ElasticsearchOperations.class);
ElasticsearchRepositoryFactory factory = new ElasticsearchRepositoryFactory(elasticsearchOperations);
return customImplementation //
.map(o -> factory.getRepository(repositoryType, o)) //
.orElseGet(() -> factory.getRepository(repositoryType));
}
/* (non-Javadoc)
* @see org.springframework.data.repository.cdi.CdiRepositoryBean#getScope()
*/
@Override
public Class<? extends Annotation> getScope() {
return elasticsearchOperationsBean.getScope();
}
}
/*
* 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.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, java.util.Optional)
*/
@Override
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType,
Optional<Object> customImplementation) {
ElasticsearchOperations elasticsearchOperations = getDependencyInstance(elasticsearchOperationsBean,
ElasticsearchOperations.class);
ElasticsearchRepositoryFactory factory = new ElasticsearchRepositoryFactory(elasticsearchOperations);
return customImplementation //
.map(o -> factory.getRepository(repositoryType, o)) //
.orElseGet(() -> factory.getRepository(repositoryType));
}
/* (non-Javadoc)
* @see org.springframework.data.repository.cdi.CdiRepositoryBean#getScope()
*/
@Override
public Class<? extends Annotation> getScope() {
return elasticsearchOperationsBean.getScope();
}
}
@@ -1,83 +1,83 @@
/*
* 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-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());
}
}
@@ -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 String-based package names.
* attribute. Use {@link #basePackageClasses()} for a type-safe alternative to text-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,106 +1,107 @@
/*
* 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()) {
query.setPageable(PageRequest.of(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(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-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();
}
}
@@ -1,50 +1,50 @@
/*
* 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-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");
}
}
@@ -1,105 +1,105 @@
/*
* 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-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();
}
}
@@ -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.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};
}
}
/*
* 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};
}
}
@@ -30,9 +30,18 @@ import org.elasticsearch.index.query.QueryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.domain.*;
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.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.query.*;
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.repository.ElasticsearchRepository;
import org.springframework.util.Assert;
@@ -45,6 +54,8 @@ 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> {
@@ -57,18 +68,18 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
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) {
this(elasticsearchOperations);
Assert.notNull(metadata, "ElasticsearchEntityInformation must not be null!");
this.entityInformation = metadata;
setEntityClass(this.entityInformation.getJavaType());
try {
@@ -94,7 +105,7 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
}
@Override
public Optional<T> findOne(ID id) {
public Optional<T> findById(ID id) {
GetQuery query = new GetQuery();
query.setId(stringIdRepresentation(id));
return Optional.ofNullable(elasticsearchOperations.queryForObject(query, getEntityClass()));
@@ -104,7 +115,7 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
public Iterable<T> findAll() {
int itemCount = (int) this.count();
if (itemCount == 0) {
return new PageImpl<>(Collections.<T>emptyList());
return new PageImpl<>(Collections.<T> emptyList());
}
return this.findAll(PageRequest.of(0, Math.max(1, itemCount)));
}
@@ -119,7 +130,7 @@ 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<>(Collections.<T> emptyList());
}
SearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
.withPageable(PageRequest.of(0, itemCount, sort)).build();
@@ -127,7 +138,7 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
}
@Override
public Iterable<T> findAll(Iterable<ID> ids) {
public Iterable<T> findAllById(Iterable<ID> ids) {
Assert.notNull(ids, "ids can't be null.");
SearchQuery query = new NativeSearchQueryBuilder().withIds(stringIdsRepresentation(ids)).build();
return elasticsearchOperations.multiGet(query, getEntityClass());
@@ -165,7 +176,7 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
}
@Override
public <S extends T> Iterable<S> save(Iterable<S> entities) {
public <S extends T> Iterable<S> saveAll(Iterable<S> entities) {
Assert.notNull(entities, "Cannot insert 'null' as a List.");
List<IndexQuery> queries = new ArrayList<>();
for (S s : entities) {
@@ -177,8 +188,8 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
}
@Override
public boolean exists(ID id) {
return findOne(id) != null;
public boolean existsById(ID id) {
return findById(id).isPresent();
}
@Override
@@ -186,7 +197,7 @@ 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<>(Collections.<T> emptyList());
}
searchQuery.setPageable(PageRequest.of(0, count));
return elasticsearchOperations.queryForPage(searchQuery, getEntityClass());
@@ -217,7 +228,7 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
}
@Override
public void delete(ID id) {
public void deleteById(ID id) {
Assert.notNull(id, "Cannot delete entity with id 'null'.");
elasticsearchOperations.delete(entityInformation.getIndexName(), entityInformation.getType(),
stringIdRepresentation(id));
@@ -227,12 +238,12 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
@Override
public void delete(T entity) {
Assert.notNull(entity, "Cannot delete 'null' entity.");
delete(extractIdFromBean(entity));
deleteById(extractIdFromBean(entity));
elasticsearchOperations.refresh(entityInformation.getIndexName());
}
@Override
public void delete(Iterable<? extends T> entities) {
public void deleteAll(Iterable<? extends T> entities) {
Assert.notNull(entities, "Cannot delete 'null' list.");
for (T entity : entities) {
delete(entity);
@@ -306,7 +317,7 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
}
protected ID extractIdFromBean(T entity) {
return entityInformation.getId(entity).orElse(null);
return entityInformation.getId(entity);
}
private List<String> stringIdsRepresentation(Iterable<ID> ids) {
@@ -1,39 +1,38 @@
/*
* 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);
}
/*
* 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);
}
@@ -1,29 +1,28 @@
/*
* 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);
}
/*
* 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);
}
@@ -1,57 +1,56 @@
/*
* 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
.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 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);
}
}
@@ -17,7 +17,6 @@ package org.springframework.data.elasticsearch.repository.support;
import static org.springframework.data.querydsl.QuerydslUtils.*;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Optional;
import java.util.UUID;
@@ -47,6 +46,7 @@ import org.springframework.util.Assert;
* @author Ryan Henszey
* @author Gad Akuka
* @author Mark Paluch
* @author Christoph Strobl
*/
public class ElasticsearchRepositoryFactory extends RepositoryFactorySupport {
@@ -54,16 +54,16 @@ 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());
}
@Override
public <T, ID extends Serializable> ElasticsearchEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
public <T, ID> ElasticsearchEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
return entityInformationCreator.getEntityInformation(domainClass);
}
@@ -1,109 +1,94 @@
/*
* 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 java.util.Optional;
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
*/
public class MappingElasticsearchEntityInformation<T, ID extends Serializable>
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() {
ElasticsearchPersistentProperty property = entityMetadata.getIdProperty()
.orElseThrow(() -> new IllegalArgumentException(String.format(
"Unable to identify 'id' property in class %s. Make sure the 'id' property is annotated with @Id or named as 'id' or 'documentId'",
entityMetadata.getType().getSimpleName())));
return property.getFieldName();
}
@Override
public String getIndexName() {
return indexName;
}
@Override
public String getType() {
return type;
}
@Override
public Long getVersion(T entity) {
Optional<ElasticsearchPersistentProperty> versionProperty = entityMetadata.getVersionProperty();
try {
return (Long) versionProperty //
.flatMap(property -> entityMetadata.getPropertyAccessor(entity).getProperty(property)) //
.orElse(null);
} catch (Exception e) {
throw new IllegalStateException("failed to load version field", e);
}
}
@Override
public String getParentId(T entity) {
Optional<ElasticsearchPersistentProperty> parentProperty = entityMetadata.getParentIdProperty();
try {
return (String) parentProperty //
.flatMap(property -> entityMetadata.getPropertyAccessor(entity).getProperty(property)) //
.orElse(null);
} catch (Exception e) {
throw new IllegalStateException("failed to load parent ID: " + e, e);
}
}
}
/*
* 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);
}
}
}
@@ -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;
}
}
+205
View File
@@ -1,6 +1,205 @@
Spring Data Elasticsearch Changelog
===================================
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).
Changes in version 3.0.0.M2 (2017-04-04)
----------------------------------------
* DATAES-342 - Adapt to API changes in RepositoryConfigurationExtensionSupport.
@@ -13,6 +212,12 @@ Changes in version 3.0.0.M2 (2017-04-04)
* DATAES-311 - Release 3.0 M2 (Kay).
Changes in version 2.0.8.RELEASE (2017-03-02)
---------------------------------------------
* DATAES-329 - Remove references to single-argument assertion methods of Spring.
* DATAES-326 - Release 2.0.8 (Hopper SR8).
Changes in version 2.1.1.RELEASE (2017-03-02)
---------------------------------------------
* DATAES-329 - Remove references to single-argument assertion methods of Spring.
+1 -1
View File
@@ -1,4 +1,4 @@
Spring Data Elasticsearch 3.0 M2
Spring Data Elasticsearch 3.0.8
Copyright (c) [2013-2016] Pivotal Software, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License").
@@ -1,72 +1,73 @@
/*
* 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()));
}
}
/*
* 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()));
}
}
@@ -1,384 +1,385 @@
/*
* 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.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")));
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<>();
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")));
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")))
.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-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()));
}
}
@@ -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);
}
}
@@ -1,139 +0,0 @@
/*
* 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 +
'}';
}
}
@@ -1,140 +0,0 @@
/*
* 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,24 +15,36 @@
*/
package org.springframework.data.elasticsearch;
import static org.elasticsearch.node.NodeBuilder.*;
import java.util.UUID;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.client.Client;
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
*/
public class Utils {
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();
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("transport.type", "local")
.put("http.type", "netty4")
.put("path.home", pathHome)
.put("path.data", pathData)
.put("cluster.name", clusterName)
.put("node.max_local_storage_nodes", 100)
.put("script.inline", "true")
.build(), asList(Netty4Plugin.class)).start().client();
}
}
@@ -1,62 +1,55 @@
/*
* 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)));
}
}
/*
* 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)));
}
}
@@ -20,6 +20,7 @@ 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;
@@ -62,7 +63,7 @@ public class EnableElasticsearchRepositoriesTests implements ApplicationContextA
static class Config {
@Bean
public ElasticsearchOperations elasticsearchTemplate() {
public ElasticsearchOperations elasticsearchTemplate() throws NodeValidationException {
return new ElasticsearchTemplate(Utils.getNodeClient());
}
}
@@ -17,6 +17,7 @@ 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;
@@ -44,7 +45,7 @@ public class EnableNestedElasticsearchRepositoriesTests {
static class Config {
@Bean
public ElasticsearchOperations elasticsearchTemplate() {
public ElasticsearchOperations elasticsearchTemplate() throws NodeValidationException {
return new ElasticsearchTemplate(Utils.getNodeClient());
}
}
@@ -29,13 +29,13 @@ public class CustomEntityMapper implements EntityMapper {
@Override
public String mapToString(Object object) throws IOException {
//mapping Object to String
//mapping Object to text
return null;
}
@Override
public <T> T mapToObject(String source, Class<T> clazz) throws IOException {
//mapping String to Object
//mapping text to Object
return null;
}
}
@@ -15,20 +15,16 @@
*/
package org.springframework.data.elasticsearch.core;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
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 java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
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.search.SearchHit;
import org.elasticsearch.search.SearchHitField;
@@ -36,7 +32,6 @@ 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;
@@ -47,12 +42,17 @@ 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 com.fasterxml.jackson.databind.util.ArrayIterator;
import static java.util.Arrays.asList;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
/**
* @author Artur Konczak
* @author Mohsin Husen
* @author Chris White
* @author Mark Paluch
*/
public class DefaultResultMapperTests {
@@ -77,12 +77,7 @@ public class DefaultResultMapperTests {
when(searchHits.iterator()).thenReturn(new ArrayIterator(hits));
when(response.getHits()).thenReturn(searchHits);
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);
Aggregations aggregations = new Aggregations(asList(createCarAggregation()));
when(response.getAggregations()).thenReturn(aggregations);
//When
@@ -91,7 +86,7 @@ public class DefaultResultMapperTests {
//Then
page.hasFacets();
assertThat(page.hasAggregations(), is(true));
assertThat(page.getAggregation("engine").getName(), is("Diesel"));
assertThat(page.getAggregation("Diesel").getName(), is("Diesel"));
}
@Test
@@ -161,6 +156,69 @@ public class DefaultResultMapperTests {
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");
@@ -190,12 +248,12 @@ public class DefaultResultMapperTests {
private Map<String, SearchHitField> createCarFields(String name, String model) {
Map<String, SearchHitField> result = new HashMap<>();
result.put("name", new InternalSearchHitField("name", Arrays.<Object>asList(name)));
result.put("model", new InternalSearchHitField("model", Arrays.<Object>asList(model)));
result.put("name", new SearchHitField("name", asList(name)));
result.put("model", new SearchHitField("model", asList(model)));
return result;
}
@Document(indexName = "someIndex")
@Document(indexName = "test-index-immutable-internal")
@NoArgsConstructor(force = true)
@Getter
static class ImmutableEntity {
@@ -16,12 +16,13 @@
package org.springframework.data.elasticsearch.core;
import static org.elasticsearch.common.xcontent.XContentFactory.*;
import static org.elasticsearch.index.query.QueryBuilders.*;
import static org.elasticsearch.join.query.JoinQueryBuilders.hasChildQuery;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.util.List;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.action.RoutingMissingException;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
@@ -80,7 +81,7 @@ public class ElasticsearchTemplateParentChildTests {
elasticsearchTemplate.refresh(ChildEntity.class);
// find all parents that have the first child
QueryBuilder query = hasChildQuery(ParentEntity.CHILD_TYPE, QueryBuilders.termQuery("name", child1name.toLowerCase()));
QueryBuilder query = hasChildQuery(ParentEntity.CHILD_TYPE, QueryBuilders.termQuery("name", child1name.toLowerCase()), ScoreMode.None);
List<ParentEntity> parents = elasticsearchTemplate.queryForList(new NativeSearchQuery(query), ParentEntity.class);
// we're expecting only the first parent as result
File diff suppressed because it is too large Load Diff
@@ -25,6 +25,7 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.junit.Test;
@@ -33,14 +34,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.builder.SampleInheritedEntityBuilder;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.data.elasticsearch.entities.*;
import org.springframework.data.elasticsearch.entities.GeoEntity;
import org.springframework.data.elasticsearch.entities.Group;
import org.springframework.data.elasticsearch.entities.MinimalEntity;
import org.springframework.data.elasticsearch.entities.SampleInheritedEntity;
import org.springframework.data.elasticsearch.entities.SampleTransientEntity;
import org.springframework.data.elasticsearch.entities.SimpleRecursiveEntity;
import org.springframework.data.elasticsearch.entities.StockPrice;
import org.springframework.data.elasticsearch.entities.User;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -49,6 +44,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
* @author Jakub Vavrik
* @author Mohsin Husen
* @author Keivn Leturc
* @author Nordine Bittich
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:elasticsearch-template-test.xml")
@@ -59,14 +55,16 @@ public class MappingBuilderTests {
@Test
public void shouldNotFailOnCircularReference() {
elasticsearchTemplate.deleteIndex(SimpleRecursiveEntity.class);
elasticsearchTemplate.createIndex(SimpleRecursiveEntity.class);
elasticsearchTemplate.putMapping(SimpleRecursiveEntity.class);
elasticsearchTemplate.refresh(SimpleRecursiveEntity.class);
}
@Test
public void testInfiniteLoopAvoidance() throws IOException {
final String expected = "{\"mapping\":{\"properties\":{\"message\":{\"store\":true,\"" +
"type\":\"string\",\"index\":\"not_analyzed\"," +
"type\":\"text\",\"index\":false," +
"\"analyzer\":\"standard\"}}}}";
XContentBuilder xContentBuilder = MappingBuilder.buildMapping(SampleTransientEntity.class, "mapping", "id", null);
@@ -121,9 +119,9 @@ public class MappingBuilderTests {
@Test
public void shouldBuildMappingWithSuperclass() throws IOException {
final String expected = "{\"mapping\":{\"properties\":{\"message\":{\"store\":true,\"" +
"type\":\"string\",\"index\":\"not_analyzed\",\"analyzer\":\"standard\"}" +
"type\":\"text\",\"index\":false,\"analyzer\":\"standard\"}" +
",\"createdDate\":{\"store\":false," +
"\"type\":\"date\",\"index\":\"not_analyzed\"}}}}";
"\"type\":\"date\",\"index\":false}}}}";
XContentBuilder xContentBuilder = MappingBuilder.buildMapping(SampleInheritedEntity.class, "mapping", "id", null);
assertThat(xContentBuilder.string(), is(expected));
@@ -186,4 +184,35 @@ public class MappingBuilderTests {
//then
}
@Test
public void shouldMapBooks() {
//given
elasticsearchTemplate.createIndex(Book.class);
elasticsearchTemplate.putMapping(Book.class);
//when
//then
}
@Test // DATAES-420
public void shouldUseBothAnalyzer() {
//given
elasticsearchTemplate.deleteIndex(Book.class);
elasticsearchTemplate.createIndex(Book.class);
elasticsearchTemplate.putMapping(Book.class);
//when
Map mapping = elasticsearchTemplate.getMapping(Book.class);
Map descriptionMapping = (Map) ((Map) mapping.get("properties")).get("description");
Map prefixDescription = (Map) ((Map) descriptionMapping.get("fields")).get("prefix");
//then
assertThat(prefixDescription.size(), is(3));
assertThat(prefixDescription.get("type"), equalTo("text"));
assertThat(prefixDescription.get("analyzer"), equalTo("stop"));
assertThat(prefixDescription.get("search_analyzer"), equalTo("standard"));
assertThat(descriptionMapping.get("type"), equalTo("text"));
assertThat(descriptionMapping.get("analyzer"), equalTo("whitespace"));
}
}
@@ -30,7 +30,7 @@ import org.springframework.data.elasticsearch.entities.SampleDateMappingEntity;
public class SimpleElasticsearchDateMappingTests {
private static final String EXPECTED_MAPPING = "{\"mapping\":{\"properties\":{\"message\":{\"store\":true," +
"\"type\":\"string\",\"index\":\"not_analyzed\",\"analyzer\":\"standard\"},\"customFormatDate\":{\"store\":false,\"type\":\"date\",\"format\":\"dd.MM.yyyy hh:mm\"}," +
"\"type\":\"text\",\"index\":false,\"analyzer\":\"standard\"},\"customFormatDate\":{\"store\":false,\"type\":\"date\",\"format\":\"dd.MM.yyyy hh:mm\"}," +
"\"defaultFormatDate\":{\"store\":false,\"type\":\"date\"},\"basicFormatDate\":{\"store\":false,\"" +
"type\":\"date\",\"format\":\"basic_date\"}}}}";
@@ -0,0 +1,41 @@
/*
* 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.aggregation;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import java.util.Arrays;
/**
* @author Remco Zigterman
*/
public class AggregatedPageImplTest {
@Test
public void constructFacetedPageWithPageable() {
Page<String> page = new AggregatedPageImpl<>(Arrays.asList("Test", "Test 2"), PageRequest.of(0, 2), 10);
assertEquals(10, page.getTotalElements());
assertEquals(2, page.getNumberOfElements());
assertEquals(2, page.getSize());
assertEquals(5, page.getTotalPages());
}
}
@@ -22,6 +22,7 @@ import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.search.aggregations.Aggregations;
import org.junit.Before;
import org.junit.Test;
@@ -36,6 +37,11 @@ import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilde
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
import static org.elasticsearch.search.aggregations.AggregationBuilders.terms;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
/**
* @author Rizwan Idrees
@@ -81,8 +87,8 @@ public class ElasticsearchTemplateAggregationTests {
// given
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(matchAllQuery())
.withSearchType(COUNT)
.withIndices("articles").withTypes("article")
.withSearchType(SearchType.DEFAULT)
.withIndices("test-index-articles").withTypes("article")
.addAggregation(terms("subjects").field("subject"))
.build();
// when
@@ -7,14 +7,14 @@ import org.springframework.data.elasticsearch.annotations.Document;
/**
* @author Mewes Kochheim
*/
@Document(indexName = "test-completion-index", type = "annotated-completion-type", shards = 1, replicas = 0, refreshInterval = "-1")
@Document(indexName = "test-index-annotated-completion", type = "annotated-completion-type", shards = 1, replicas = 0, refreshInterval = "-1")
public class AnnotatedCompletionEntity {
@Id
private String id;
private String name;
@CompletionField(payloads = true, maxInputLength = 100)
@CompletionField(maxInputLength = 100)
private Completion suggest;
private AnnotatedCompletionEntity() {
@@ -36,23 +36,12 @@ public class AnnotatedCompletionEntityBuilder {
}
public AnnotatedCompletionEntityBuilder suggest(String[] input) {
return suggest(input, null, null, null);
return suggest(input, null);
}
public AnnotatedCompletionEntityBuilder suggest(String[] input, String output) {
return suggest(input, output, null, null);
}
public AnnotatedCompletionEntityBuilder suggest(String[] input, String output, Object payload) {
return suggest(input, output, payload, null);
}
public AnnotatedCompletionEntityBuilder suggest(String[] input, String output, Object payload, Integer weight) {
public AnnotatedCompletionEntityBuilder suggest(String[] input, Integer weight) {
Completion suggest = new Completion(input);
suggest.setOutput(output);
suggest.setPayload(payload);
suggest.setWeight(weight);
result.setSuggest(suggest);
return this;
}
@@ -9,14 +9,14 @@ import org.springframework.data.elasticsearch.annotations.Document;
* @author Mohsin Husen
* @author Mewes Kochheim
*/
@Document(indexName = "test-completion-index", type = "completion-annotation-type", shards = 1, replicas = 0, refreshInterval = "-1")
@Document(indexName = "test-index-completion-annotated", type = "completion-annotation-type", shards = 1, replicas = 0, refreshInterval = "-1")
public class CompletionAnnotatedEntity {
@Id
private String id;
private String name;
@CompletionField(payloads = true)
@CompletionField
private Completion suggest;
private CompletionAnnotatedEntity() {
@@ -7,7 +7,7 @@ import org.springframework.data.elasticsearch.annotations.Document;
/**
* @author Mewes Kochheim
*/
@Document(indexName = "test-completion-index", type = "completion-type", shards = 1, replicas = 0, refreshInterval = "-1")
@Document(indexName = "test-index-completion", type = "completion-type", shards = 1, replicas = 0, refreshInterval = "-1")
public class CompletionEntity {
@Id
@@ -36,25 +36,11 @@ public class CompletionEntityAnnotatedBuilder {
}
public CompletionEntityAnnotatedBuilder suggest(String[] input) {
return suggest(input, null, null, null);
return suggest(input, null);
}
public CompletionEntityAnnotatedBuilder suggest(String[] input, String output) {
return suggest(input, output, null, null);
}
public CompletionEntityAnnotatedBuilder suggest(String[] input, String output, Object payload) {
return suggest(input, output, payload, null);
}
public CompletionEntityAnnotatedBuilder suggest(String[] input, String output, Object payload, Integer weight) {
public CompletionEntityAnnotatedBuilder suggest(String[] input, Integer weight) {
Completion suggest = new Completion(input);
if (output != null) {
suggest.setOutput(output);
}
if (payload != null) {
suggest.setPayload(payload);
}
if (weight != null) {
suggest.setWeight(weight);
}
@@ -34,21 +34,11 @@ public class CompletionEntityBuilder {
}
public CompletionEntityBuilder suggest(String[] input) {
return suggest(input, null, null, null);
return suggest(input, null);
}
public CompletionEntityBuilder suggest(String[] input, String output) {
return suggest(input, output, null, null);
}
public CompletionEntityBuilder suggest(String[] input, String output, Object payload) {
return suggest(input, output, payload, null);
}
public CompletionEntityBuilder suggest(String[] input, String output, Object payload, Integer weight) {
public CompletionEntityBuilder suggest(String[] input, Integer weight) {
Completion suggest = new Completion(input);
suggest.setOutput(output);
suggest.setPayload(payload);
suggest.setWeight(weight);
result.setSuggest(suggest);
@@ -22,9 +22,13 @@ import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.List;
import org.elasticsearch.action.suggest.SuggestResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.search.suggest.SuggestionBuilder;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.elasticsearch.search.suggest.completion.CompletionSuggestionFuzzyBuilder;
import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -34,6 +38,13 @@ import org.springframework.data.elasticsearch.entities.NonDocumentEntity;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.ArrayList;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertEquals;
/**
* @author Rizwan Idrees
* @author Mohsin Husen
@@ -57,8 +68,8 @@ public class ElasticsearchTemplateCompletionTests {
List<IndexQuery> indexQueries = new ArrayList<>();
indexQueries.add(new CompletionEntityBuilder("1").name("Rizwan Idrees").suggest(new String[]{"Rizwan Idrees"}).buildIndex());
indexQueries.add(new CompletionEntityBuilder("2").name("Franck Marchand").suggest(new String[]{"Franck", "Marchand"}).buildIndex());
indexQueries.add(new CompletionEntityBuilder("3").name("Mohsin Husen").suggest(new String[]{"Mohsin", "Husen"}, "Mohsin Husen").buildIndex());
indexQueries.add(new CompletionEntityBuilder("4").name("Artur Konczak").suggest(new String[]{"Artur", "Konczak"}, "Artur Konczak").buildIndex());
indexQueries.add(new CompletionEntityBuilder("3").name("Mohsin Husen").suggest(new String[]{"Mohsin", "Husen"}).buildIndex());
indexQueries.add(new CompletionEntityBuilder("4").name("Artur Konczak").suggest(new String[]{"Artur", "Konczak"}).buildIndex());
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(CompletionEntity.class);
@@ -76,29 +87,9 @@ public class ElasticsearchTemplateCompletionTests {
List<IndexQuery> indexQueries = new ArrayList<>();
indexQueries.add(new AnnotatedCompletionEntityBuilder("1").name("Franck Marchand").suggest(new String[]{"Franck", "Marchand"}).buildIndex());
indexQueries.add(new AnnotatedCompletionEntityBuilder("2").name("Mohsin Husen").suggest(new String[]{"Mohsin", "Husen"}, "Mohsin Husen").buildIndex());
indexQueries.add(new AnnotatedCompletionEntityBuilder("3").name("Rizwan Idrees").suggest(new String[]{"Rizwan", "Idrees"}, "Rizwan Idrees").buildIndex());
indexQueries.add(new AnnotatedCompletionEntityBuilder("4").name("Artur Konczak").suggest(new String[]{"Artur", "Konczak"}, "Artur Konczak").buildIndex());
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(AnnotatedCompletionEntity.class);
}
private void loadAnnotatedCompletionObjectEntitiesWithPayloads() {
elasticsearchTemplate.deleteIndex(AnnotatedCompletionEntity.class);
elasticsearchTemplate.createIndex(AnnotatedCompletionEntity.class);
elasticsearchTemplate.refresh(AnnotatedCompletionEntity.class);
elasticsearchTemplate.putMapping(AnnotatedCompletionEntity.class);
NonDocumentEntity nonDocumentEntity = new NonDocumentEntity();
nonDocumentEntity.setSomeField1("Payload");
nonDocumentEntity.setSomeField2("test");
List<IndexQuery> indexQueries = new ArrayList<>();
indexQueries.add(new AnnotatedCompletionEntityBuilder("1").name("Mewes Kochheim1").suggest(new String[]{"Mewes Kochheim1"}, null, Double.MAX_VALUE).buildIndex());
indexQueries.add(new AnnotatedCompletionEntityBuilder("2").name("Mewes Kochheim2").suggest(new String[]{"Mewes Kochheim2"}, null, Long.MAX_VALUE).buildIndex());
indexQueries.add(new AnnotatedCompletionEntityBuilder("3").name("Mewes Kochheim3").suggest(new String[]{"Mewes Kochheim3"}, null, "Payload test").buildIndex());
indexQueries.add(new AnnotatedCompletionEntityBuilder("4").name("Mewes Kochheim4").suggest(new String[]{"Mewes Kochheim4"}, null, nonDocumentEntity).buildIndex());
indexQueries.add(new AnnotatedCompletionEntityBuilder("2").name("Mohsin Husen").suggest(new String[]{"Mohsin", "Husen"}).buildIndex());
indexQueries.add(new AnnotatedCompletionEntityBuilder("3").name("Rizwan Idrees").suggest(new String[]{"Rizwan", "Idrees"}).buildIndex());
indexQueries.add(new AnnotatedCompletionEntityBuilder("4").name("Artur Konczak").suggest(new String[]{"Artur", "Konczak"}).buildIndex());
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(AnnotatedCompletionEntity.class);
@@ -107,14 +98,14 @@ public class ElasticsearchTemplateCompletionTests {
private void loadAnnotatedCompletionObjectEntitiesWithWeights() {
elasticsearchTemplate.deleteIndex(AnnotatedCompletionEntity.class);
elasticsearchTemplate.createIndex(AnnotatedCompletionEntity.class);
elasticsearchTemplate.refresh(AnnotatedCompletionEntity.class);
elasticsearchTemplate.putMapping(AnnotatedCompletionEntity.class);
elasticsearchTemplate.refresh(AnnotatedCompletionEntity.class);
List<IndexQuery> indexQueries = new ArrayList<>();
indexQueries.add(new AnnotatedCompletionEntityBuilder("1").name("Mewes Kochheim1").suggest(new String[]{"Mewes Kochheim1"}).buildIndex());
indexQueries.add(new AnnotatedCompletionEntityBuilder("2").name("Mewes Kochheim2").suggest(new String[]{"Mewes Kochheim2"}, null, null, 0).buildIndex());
indexQueries.add(new AnnotatedCompletionEntityBuilder("3").name("Mewes Kochheim3").suggest(new String[]{"Mewes Kochheim3"}, null, null, 1).buildIndex());
indexQueries.add(new AnnotatedCompletionEntityBuilder("4").name("Mewes Kochheim4").suggest(new String[]{"Mewes Kochheim4"}, null, null, Integer.MAX_VALUE).buildIndex());
indexQueries.add(new AnnotatedCompletionEntityBuilder("1").name("Mewes Kochheim1").suggest(new String[]{"Mewes Kochheim1"},4).buildIndex());
indexQueries.add(new AnnotatedCompletionEntityBuilder("2").name("Mewes Kochheim2").suggest(new String[]{"Mewes Kochheim2"}, 1).buildIndex());
indexQueries.add(new AnnotatedCompletionEntityBuilder("3").name("Mewes Kochheim3").suggest(new String[]{"Mewes Kochheim3"}, 2).buildIndex());
indexQueries.add(new AnnotatedCompletionEntityBuilder("4").name("Mewes Kochheim4").suggest(new String[]{"Mewes Kochheim4"}, Integer.MAX_VALUE).buildIndex());
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(AnnotatedCompletionEntity.class);
@@ -134,81 +125,45 @@ public class ElasticsearchTemplateCompletionTests {
public void shouldFindSuggestionsForGivenCriteriaQueryUsingCompletionEntity() {
//given
loadCompletionObjectEntities();
CompletionSuggestionFuzzyBuilder completionSuggestionFuzzyBuilder = new CompletionSuggestionFuzzyBuilder("test-suggest")
.text("m")
.field("suggest");
SuggestionBuilder completionSuggestionFuzzyBuilder = SuggestBuilders.completionSuggestion("suggest").prefix("m", Fuzziness.AUTO);
//when
SuggestResponse suggestResponse = elasticsearchTemplate.suggest(completionSuggestionFuzzyBuilder, CompletionEntity.class);
final SearchResponse suggestResponse = elasticsearchTemplate.suggest(new SuggestBuilder().addSuggestion("test-suggest",completionSuggestionFuzzyBuilder), CompletionEntity.class);
CompletionSuggestion completionSuggestion = suggestResponse.getSuggest().getSuggestion("test-suggest");
List<CompletionSuggestion.Entry.Option> options = completionSuggestion.getEntries().get(0).getOptions();
//then
assertThat(options.size(), is(2));
assertThat(options.get(0).getText().string(), isOneOf("Marchand", "Mohsin Husen"));
assertThat(options.get(1).getText().string(), isOneOf("Marchand", "Mohsin Husen"));
assertThat(options.get(0).getText().string(), isOneOf("Marchand", "Mohsin"));
assertThat(options.get(1).getText().string(), isOneOf("Marchand", "Mohsin"));
}
@Test
public void shouldFindSuggestionsForGivenCriteriaQueryUsingAnnotatedCompletionEntity() {
//given
loadAnnotatedCompletionObjectEntities();
CompletionSuggestionFuzzyBuilder completionSuggestionFuzzyBuilder = new CompletionSuggestionFuzzyBuilder("test-suggest")
.text("m")
.field("suggest");
SuggestionBuilder completionSuggestionFuzzyBuilder = SuggestBuilders.completionSuggestion("suggest").prefix("m", Fuzziness.AUTO);
//when
SuggestResponse suggestResponse = elasticsearchTemplate.suggest(completionSuggestionFuzzyBuilder, CompletionEntity.class);
final SearchResponse suggestResponse = elasticsearchTemplate.suggest(new SuggestBuilder().addSuggestion("test-suggest", completionSuggestionFuzzyBuilder), CompletionEntity.class);
CompletionSuggestion completionSuggestion = suggestResponse.getSuggest().getSuggestion("test-suggest");
List<CompletionSuggestion.Entry.Option> options = completionSuggestion.getEntries().get(0).getOptions();
//then
assertThat(options.size(), is(2));
assertThat(options.get(0).getText().string(), isOneOf("Marchand", "Mohsin Husen"));
assertThat(options.get(1).getText().string(), isOneOf("Marchand", "Mohsin Husen"));
}
@Test
public void shouldFindSuggestionsWithPayloadsForGivenCriteriaQueryUsingAnnotatedCompletionEntity() {
//given
loadAnnotatedCompletionObjectEntitiesWithPayloads();
CompletionSuggestionFuzzyBuilder completionSuggestionFuzzyBuilder = new CompletionSuggestionFuzzyBuilder("test-suggest")
.text("m")
.field("suggest");
//when
SuggestResponse suggestResponse = elasticsearchTemplate.suggest(completionSuggestionFuzzyBuilder, CompletionEntity.class);
CompletionSuggestion completionSuggestion = suggestResponse.getSuggest().getSuggestion("test-suggest");
List<CompletionSuggestion.Entry.Option> options = completionSuggestion.getEntries().get(0).getOptions();
//then
assertThat(options.size(), is(4));
for (CompletionSuggestion.Entry.Option option : options) {
if (option.getText().string().equals("Mewes Kochheim1")) {
assertEquals(Double.MAX_VALUE, option.getPayloadAsDouble(), 0);
} else if (option.getText().string().equals("Mewes Kochheim2")) {
assertEquals(Long.MAX_VALUE, option.getPayloadAsLong());
} else if (option.getText().string().equals("Mewes Kochheim3")) {
assertEquals("Payload test", option.getPayloadAsString());
} else if (option.getText().string().equals("Mewes Kochheim4")) {
assertEquals("Payload", option.getPayloadAsMap().get("someField1"));
assertEquals("test", option.getPayloadAsMap().get("someField2"));
} else {
fail("Unexpected option");
}
}
assertThat(options.get(0).getText().string(), isOneOf("Marchand", "Mohsin"));
assertThat(options.get(1).getText().string(), isOneOf("Marchand", "Mohsin"));
}
@Test
public void shouldFindSuggestionsWithWeightsForGivenCriteriaQueryUsingAnnotatedCompletionEntity() {
//given
loadAnnotatedCompletionObjectEntitiesWithWeights();
CompletionSuggestionFuzzyBuilder completionSuggestionFuzzyBuilder = new CompletionSuggestionFuzzyBuilder("test-suggest")
.text("m")
.field("suggest");
SuggestionBuilder completionSuggestionFuzzyBuilder = SuggestBuilders.completionSuggestion("suggest").prefix("m", Fuzziness.AUTO);
//when
SuggestResponse suggestResponse = elasticsearchTemplate.suggest(completionSuggestionFuzzyBuilder, CompletionEntity.class);
final SearchResponse suggestResponse = elasticsearchTemplate.suggest(new SuggestBuilder().addSuggestion("test-suggest",completionSuggestionFuzzyBuilder), AnnotatedCompletionEntity.class);
CompletionSuggestion completionSuggestion = suggestResponse.getSuggest().getSuggestion("test-suggest");
List<CompletionSuggestion.Entry.Option> options = completionSuggestion.getEntries().get(0).getOptions();
@@ -218,9 +173,9 @@ public class ElasticsearchTemplateCompletionTests {
if (option.getText().string().equals("Mewes Kochheim1")) {
assertEquals(4, option.getScore(), 0);
} else if (option.getText().string().equals("Mewes Kochheim2")) {
assertEquals(0, option.getScore(), 0);
} else if (option.getText().string().equals("Mewes Kochheim3")) {
assertEquals(1, option.getScore(), 0);
} else if (option.getText().string().equals("Mewes Kochheim3")) {
assertEquals(2, option.getScore(), 0);
} else if (option.getText().string().equals("Mewes Kochheim4")) {
assertEquals(Integer.MAX_VALUE, option.getScore(), 0);
} else {

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