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

Compare commits

...

118 Commits

Author SHA1 Message Date
Oliver Gierke 51ca555470 DATAES-304 - Release version 2.0.6 (Hopper SR6). 2016-12-21 19:04:47 +01:00
Oliver Gierke bc4891907e DATAES-304 - Prepare 2.0.6 (Hopper SR6). 2016-12-21 19:03:40 +01:00
Oliver Gierke 96934676ae DATAES-304 - Updated changelog. 2016-12-21 19:03:36 +01:00
Oliver Gierke 90348459e7 DATAES-275 - Updated changelog. 2016-12-21 18:43:08 +01:00
Oliver Gierke e2a868ef97 DATAES-306 - Updated changelog. 2016-11-23 13:52:50 +01:00
Oliver Gierke 0c146bb47c DATAES-300 - After release cleanups. 2016-11-03 18:20:12 +01:00
Oliver Gierke 35ad47da4a DATAES-300 - Prepare next development iteration. 2016-11-03 18:20:10 +01:00
Oliver Gierke fd33ad40d7 DATAES-300 - Release version 2.0.5 (Hopper SR5). 2016-11-03 17:56:33 +01:00
Oliver Gierke ac7ee3e986 DATAES-300 - Prepare 2.0.5 (Hopper SR5). 2016-11-03 17:56:00 +01:00
Oliver Gierke 729ecb2ed9 DATAES-300 - Updated changelog. 2016-11-03 17:55:57 +01:00
Oliver Gierke 89b99c7687 DATAES-297 - After release cleanups. 2016-09-29 14:20:14 +02:00
Oliver Gierke 4498805d0d DATAES-297 - Prepare next development iteration. 2016-09-29 14:20:10 +02:00
Oliver Gierke c781fde4b4 DATAES-297 - Release version 2.0.4 (Hopper SR4). 2016-09-29 13:54:04 +02:00
Oliver Gierke 67385a9c51 DATAES-297 - Prepare 2.0.4 (Hopper SR4). 2016-09-29 13:53:27 +02:00
Oliver Gierke 30cf3b5172 DATAES-297 - Updated changelog. 2016-09-29 13:53:23 +02:00
Oliver Gierke baa52a82e4 DATAES-299 - Updated changelog. 2016-09-29 11:42:12 +02:00
Oliver Gierke 397d3b89f8 DATAES-296 - Updated changelog. 2016-09-21 07:28:59 +02:00
Oliver Gierke abd6ad3536 DATAES-268 - After release cleanups. 2016-09-20 11:19:05 +02:00
Oliver Gierke 0510b06ee4 DATAES-268 - Prepare next development iteration. 2016-09-20 11:19:01 +02:00
Oliver Gierke ff1f7676b2 DATAES-268 - Release version 2.0.3 (Hopper SR3). 2016-09-20 10:54:51 +02:00
Oliver Gierke 10a11ad22f DATAES-268 - Prepare 2.0.3 (Hopper SR3). 2016-09-20 10:54:17 +02:00
Oliver Gierke 0978c47fb9 DATAES-268 - Updated changelog. 2016-09-20 10:54:14 +02:00
Oliver Gierke acc81f89fb DATAES-281 - Polishing.
Added unit test for change in DefaultResultMapperTests. Tweaked and simplified integration tests.

Make use of IdentifierAccessor in ElasticsearcTemplate.getPersistentEntityId(…). Added missing generics in DefaultResultMapper.

Removed unused imports, fixed copyright ranges, authors.

Original pull request: #156.
2016-08-20 10:07:59 +02:00
Young Gu 4fb2b33066 DATAES-281 - Setting identifier values now uses PersistentPropertyAccessor API.
DefaultResultMapper and ElasticsearchTemplate now use the PersistentPropertyAccessor API to set identifier values on objects instead of using reflection.

Original pull request: #156.
2016-08-20 10:04:09 +02:00
Oliver Gierke 20d8103a19 DATAES-250 - Updated changelog. 2016-07-28 08:50:39 +02:00
Artur Konczak c799e8d1c8 DATAES-262 - added profile to build project with ES 2.3.3 2016-06-17 09:31:49 +01:00
Oliver Gierke e4e6b09161 DATAES-251 - After release cleanups. 2016-06-15 14:17:54 +02:00
Oliver Gierke 511da0fadf DATAES-251 - Prepare next development iteration. 2016-06-15 14:17:52 +02:00
Oliver Gierke 6090f4a5db DATAES-251 - Release version 2.0.2 (Hopper SR2). 2016-06-15 13:45:53 +02:00
Oliver Gierke c964ce5dac DATAES-251 - Prepare 2.0.2 (Hopper SR2). 2016-06-15 13:44:54 +02:00
Oliver Gierke 2f50462857 DATAES-251 - Updated changelog. 2016-06-15 13:44:49 +02:00
Oliver Gierke eab54cb546 DATAES-249 - After release cleanups. 2016-04-06 22:51:45 +02:00
Oliver Gierke 6bdb45a0f8 DATAES-249 - Prepare next development iteration. 2016-04-06 22:51:43 +02:00
Oliver Gierke 793e6ab843 DATAES-249 - Release version 2.0.1 (Hopper SR1). 2016-04-06 22:32:15 +02:00
Oliver Gierke 182684e56c DATAES-249 - Prepare 2.0.1 (Hopper SR1). 2016-04-06 22:31:41 +02:00
Oliver Gierke 33e1611186 DATAES-249 - Updated changelog. 2016-04-06 22:31:38 +02:00
Oliver Gierke 55ccfe5c0b DATAES-245 - Prepare next development iteration. 2016-04-06 16:38:19 +02:00
Oliver Gierke a362361ace DATAES-245 - Release version 2.0 GA (Hopper). 2016-04-06 16:35:59 +02:00
Oliver Gierke d9e66aa532 DATAES-245 - Prepare 2.0 GA (Hopper). 2016-04-06 16:34:47 +02:00
Oliver Gierke 5094482b6c DATAES-245 - Updated changelog. 2016-04-06 16:34:42 +02:00
Artur Konczak b6a8f2f832 DATAES-248 - updated jira link to point to correct project on jira 2016-04-05 10:42:17 +01:00
Mark Paluch c856680523 DATAES-248 - Add pull request template.
Original pull request: #143.
2016-04-05 10:23:05 +01:00
Artur Konczak ef0831fa33 DATAES-105 - support for IP6 2016-04-04 10:31:32 +01:00
Mohsin Husen b2f0300856 DATAES-240 - After release cleanups. 2016-03-18 10:44:11 +00:00
Oliver Gierke 246da57993 DATAES-240 - After release cleanups. 2016-03-18 11:16:08 +01:00
Oliver Gierke 72ca7477fc DATAES-240 - Prepare next development iteration. 2016-03-18 11:15:51 +01:00
Oliver Gierke 3a41435155 DATAES-240 - Release version 2.0 RC1 (Hopper). 2016-03-18 11:15:00 +01:00
Oliver Gierke cbb3a7afc4 DATAES-240 - Prepare 2.0 RC1 (Hopper). 2016-03-18 11:06:58 +01:00
Oliver Gierke 800b10b2b1 DATAES-240 - Updated changelog. 2016-03-18 11:06:55 +01:00
Mark Paluch 023214a344 DATAES-234 - Use Set to store qualifiers in CDI extension.
Qualifiers are now stored in their original set instead of using the toString representation.
2016-03-17 14:52:39 +00:00
Mohsin Husen 477e8e2a07 DATAES-241 - Remove commons-collections dependency 2016-03-16 15:36:01 +00:00
Mohsin Husen 374acbdd63 DATAES-124 - ElasticSearchTemplate should expose client 2016-03-15 11:34:41 +00:00
Markus Ackermann 8bb4ac3653 DATAES-238 - Fix ElasticsearchTemplate.prepareUpdate(): preserve routing
* need to specify Locale.ENGLISH in String.format()
  to make tests succeed on non-english locales

* that's because the String.format involves floating
  point numbers which are formatted differently in
  some locales

* ElasticsearchTemplate.prepareUpdate() properly copies routing
  from given UpdateRequest

* add unit tests to ElasticsearchTemplateParentChildTests
  for update of a child document
2016-03-15 11:16:57 +00:00
Mohsin Husen 907571e550 DATAES-211 - clean up
update readme
2016-03-11 12:04:14 +00:00
Mohsin Husen f98d888151 DATAES-240 - Bump version to 2.0
update readme
2016-03-09 09:55:12 +00:00
Mohsin Husen a8d915f830 DATAES-241 - Remove commons-collections dependency and use CollectionUtils from Spring Utils 2016-03-08 15:24:51 +00:00
Mohsin Husen f493db7774 DATAES-240 - Bump version to 2.0
There are breaking changes that demands a major version upgrade of spring-data-elasticsearch
2016-03-07 14:43:01 +00:00
Mohsin Husen c4b4a8c45d DATAES-188 - Source filtering feature Implementation 2016-03-03 14:53:18 +00:00
Joseph Moore 1cf18a4a50 DATAES-237 - path-configuration fails to load configs from inside jars 2016-02-26 15:18:12 +00:00
Mohsin Husen 6535caff8a DATAES-236 - fix test for build failure 2016-02-26 15:00:36 +00:00
Mohsin Husen 2aa7ed1c23 DATAES-236 - Clear the search contexts associated with specified scroll id 2016-02-26 14:54:51 +00:00
Mohsin Husen 0f6004ae94 DATAES-211 - update read me for elasticsearch version information. 2016-02-25 09:44:57 +00:00
Mohsin Husen e9576adb1a DATAES-211 - build fix, ignore test 2016-02-24 13:42:07 +00:00
Mohsin Husen ca7a7fb382 DATAES-211 - updated readme for elasticsearch version information 2016-02-24 13:14:03 +00:00
Mohsin Husen c5c9956bc0 DATAES-211 - clean up
remove waitForOperation from refresh()
enhance GeoPoint and Point feature
code clean up
2016-02-24 12:45:37 +00:00
Mohsin Husen 4930415302 DATAES-211 - Fix tests for CDI (jar hell) 2016-02-24 12:45:36 +00:00
Mohsin Husen 42fc41b2eb DATAES-211 - clean up
remove facet feature as it is removed in elasticsearch 2.x
2016-02-24 12:45:36 +00:00
Mohsin Husen 4e0cbb8966 DATAES-211
changes in AliasRequest
 fix tests due to changes in mapping, geo point, alias etc
2016-02-24 12:45:36 +00:00
Mohsin Husen 95194961dc DATAES-211 - move groovy scripting into test folder 2016-02-24 12:45:36 +00:00
Mohsin Husen 6a2b5fd945 DATAES-211 - entity should have suggest mapping 2016-02-24 12:45:35 +00:00
Mohsin Husen 4efec54e1d DATAES-211 - incorporate changes in GeoDistance 2016-02-24 12:45:35 +00:00
Mohsin Husen c7313b52eb DATAES-211 - index analyzer is removed. use analyzer for search and index analyzer or use search analyzer. 2016-02-24 12:45:35 +00:00
Mohsin Husen a05a597123 DATAES-211 - index analyzer is removed. use analyzer for search and index analyzer or use search analyzer. 2016-02-24 12:45:35 +00:00
Mohsin Husen 61880671a4 DATAES-211 - enhance multi field support as multifield type is removed 2016-02-24 12:45:35 +00:00
Mohsin Husen 09455006ab DATAES-211 - enable groovy for scripting 2016-02-24 12:45:35 +00:00
Mohsin Husen 924467ec94 DATAES-211 -clean up 2016-02-24 12:45:34 +00:00
Artur Konczak 8963123ffe DATAES-211 - updated to ES-2.2, test fixes round 1 2016-02-24 12:45:34 +00:00
Oliver Gierke a853ca359a DATAES-231 - After release cleanups. 2016-02-12 15:43:57 +01:00
Oliver Gierke 76d8d5fe3e DATAES-231 - Prepare next development iteration. 2016-02-12 15:43:39 +01:00
Oliver Gierke de821410f2 DATAES-231 - Release version 1.4 M1 (Hopper). 2016-02-12 15:42:47 +01:00
Oliver Gierke ba8bd886d4 DATAES-231 - Prepare 1.4 M1 (Hopper). 2016-02-12 15:36:20 +01:00
Oliver Gierke fd4b74313f DATAES-231 - Updated changelog. 2016-02-12 15:36:16 +01:00
Oliver Gierke fad5162b26 DATAES-232 - Added code of conduct.
Added CONTRIBUTING file along the way.
2016-02-02 10:59:29 +01:00
Oliver Gierke d5cdba06b3 DATA_ES-231 - Declare Artifactory Maven plugin to be able to distribute build artifacts. 2016-01-28 15:01:50 +01:00
slowikps 4296760eb0 DATAES-230 - Remove unnecessary type check in AbstractElasticsearchRepository 2016-01-26 15:38:51 +00:00
Ted Liang 403a85b094 DATAES-209 - Dynamic mapping using @Mapping Annotation at field level
fix test

fix comment in test
2016-01-26 15:22:16 +00:00
Mohsin Husen 428cac3642 DATAES-216 - cleanup 2016-01-26 15:04:00 +00:00
Thiago Locatelli ba1fb9fc6f DATAES-216 - Adding support to 'indices_boost' when searching against multiple indices
Applying spring-data code format

Merge branch 'master' of https://github.com/thiagolocatelli/spring-data-elasticsearch into thiagolocatelli-master
2016-01-26 14:57:00 +00:00
pkraeutli 9c91723833 DATAES-224 retain newlines when reading mapping/setting files
Fixed test-settings yaml
2016-01-26 14:42:34 +00:00
Artur Konczak 7dbab75cf5 DATAES-50 - Enabled support for scripts for node client, added missing groovy lib 2015-12-31 02:09:11 +00:00
Ryan Murfitt d6603f8edf DATAES-50 - Added scripted field functionality 2015-12-31 02:08:38 +00:00
Kevin Leturc 727cb5eb09 DATAES-141 - Update ElasticsearchTemplate constructors to init properly the default implementations. 2015-12-28 00:26:20 +00:00
Oliver Gierke aa44da63f9 DATAES-223 - Updated changelog. 2015-12-18 11:26:11 +01:00
Kevin Leturc 23e1e9f46a DATAES-217 Propose scan method with a class in order to retrieve index and type from Document 2015-12-17 00:47:01 +00:00
Mason Chan 751302d6f0 DATAES-143 added support for turning off auto index creation based on Document annotation. 2015-12-16 01:53:49 +00:00
Oliver Gierke 485f0e7252 DATAES-221 - Adapted to API changes in Spring Data Commons.
Related ticket: DATACMNS-89.
2015-12-14 21:13:33 +01:00
dianandonov aa9c47516c DATAES-208 - Allow node configuration to honor the server settings in @Document 2015-12-12 02:18:24 +00:00
Artur Konczak 21ff7e50cf DATAES-206 - added GEO_POINT support for Point from Spring Data Commons 2015-12-08 12:03:25 +00:00
Oliver Gierke 909caa732b DATAES-212 - Updated changelog. 2015-11-16 08:51:36 +01:00
Nicolas François 5b850c61e2 DATAES-210 - Typo in error message 2015-11-04 16:41:44 +00:00
Mohsin Husen 9981ad0dba DATAES-94 - upgrade to latest elasticsearch 1.7.3 driver 2015-11-04 16:11:57 +00:00
Oliver Gierke bcc763b97b DATAES-202 - Updated changelog. 2015-10-14 13:57:59 +02:00
Mohsin Husen 131b172ce2 DATAES-94 - upgrade to latest elasticsearch 1.7.2 driver 2015-09-30 17:04:44 +01:00
Kevin Leturc 7d645ac5e1 DATAES-200 Set persistent entity index and type in query when no indices/types are set. 2015-09-23 13:23:00 +02:00
Artur Konczak 4350234299 DATAES-179 - added support for Attachment field type 2015-09-19 00:16:59 +01:00
Artur Konczak 5a648bcb7a DATAES-172 - added test to cover geohash prefix 2015-09-18 16:16:46 +01:00
dianandonov 6a06bbfbb9 DATAES-172 - Added support for "geohash_prefix" and "geohash_precision" on GeoPointField annotation 2015-09-17 23:10:51 +01:00
Mohsin Husen c2f13c3820 DATAES-194 - Tests should clean up "data" directory. 2015-09-17 12:02:51 +01:00
Artur Konczak 49708d38c0 DATAES-171 - added support for missing query keywords 2015-09-17 09:11:57 +01:00
Mohsin Husen d9212630b9 DATAES-193 - After release cleanups 2015-09-02 11:53:44 +01:00
Oliver Gierke 9682e7ee28 DATAES-193 - After release cleanups. 2015-09-01 12:11:03 +02:00
Spring Buildmaster a6d4109d0b DATAES-193 - Prepare next development iteration. 2015-09-01 01:53:56 -07:00
Spring Buildmaster 6a6c44401d DATAES-193 - Release version 1.3.0.RELEASE (Gosling GA). 2015-09-01 01:53:54 -07:00
Oliver Gierke 7f4ee37be3 DATAES-193 - Prepare 1.3.0.RELEASE (Gosling GA). 2015-09-01 10:13:36 +02:00
Oliver Gierke bc8b5b8bd8 DATAES-193 - Updated changelog. 2015-09-01 10:13:33 +02:00
Artur Konczak 6cdc765b24 DATAES-137 - set missing MappingContext in ElasticsearchRepositoryFactoryBean 2015-08-29 01:49:18 +01:00
Oliver Gierke f9e0b3a4f9 DATAES-186 - After release cleanups. 2015-08-04 14:09:22 +02:00
Spring Buildmaster 52fec26a1d DATAES-186 - Prepare next development iteration. 2015-08-04 04:29:19 -07:00
171 changed files with 3603 additions and 2891 deletions
+9
View File
@@ -0,0 +1,9 @@
Thank you for proposing a pull request. This template will guide you through the essential steps necessary for a pull request.
Make sure that:
- [ ] You have read the [Spring Data contribution guidelines](https://github.com/spring-projects/spring-data-build/blob/master/CONTRIBUTING.adoc).
- [ ] There is a ticket in the bug tracker for the project in our [JIRA](https://jira.spring.io/browse/DATAES).
- [ ] You use the code formatters provided [here](https://github.com/spring-projects/spring-data-build/tree/master/etc/ide) and have them applied to your changes. Dont submit any formatting related changes.
- [ ] You submit test cases (unit or integration tests) that back your changes.
- [ ] You added yourself as author in the headers of the classes you touched. Amend the date range in the Apache license header if needed. For new types, add the license header (copy from another file and set the current year only).
- [ ] You provide your full name and an email address registered with your GitHub account. If youre a first-time submitter, make sure you have completed the [Contributors License Agreement form](https://support.springsource.com/spring_committer_signup).
+27
View File
@@ -0,0 +1,27 @@
= Contributor Code of Conduct
As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery
* Personal attacks
* Trolling or insulting/derogatory comments
* Public or private harassment
* Publishing other's private information, such as physical or electronic addresses,
without explicit permission
* Other unethical or unprofessional conduct
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a project maintainer at spring-code-of-conduct@pivotal.io.
All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances.
Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident.
This Code of Conduct is adapted from the http://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at http://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/].
+3
View File
@@ -0,0 +1,3 @@
= Spring Data contribution guidelines
You find the contribution guidelines for Spring Data projects https://github.com/spring-projects/spring-data-build/blob/master/CONTRIBUTING.adoc[here].
+19 -8
View File
@@ -11,12 +11,12 @@ Guide
------------
* [Reference Documentation](http://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/)
* [PDF Documentation](http://docs.spring.io/spring-data/elasticsearch/docs/current/reference/pdf/spring-data-elasticsearch-reference.pdf)
* [API Documentation](http://docs.spring.io/spring-data/elasticsearch/docs/current/api/)
* [Spring Data Project](http://projects.spring.io/spring-data)
* [Sample Test Application](https://github.com/BioMedCentralLtd/spring-data-elasticsearch-sample-application)
* [Issues](https://jira.springsource.org/browse/DATAES)
* [Spring Data Elasticsearch Google Group](https://groups.google.com/d/forum/spring-data-elasticsearch-devs)
* For more detailed questions, use the [forum](http://forum.springsource.org/forumdisplay.php?f=80).
* [Questions](http://stackoverflow.com/questions/tagged/spring-data-elasticsearch)
Quick Start
@@ -31,7 +31,7 @@ Add the Maven dependency:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>1.2.0.RELEASE</version>
<version>1.3.4.RELEASE</version>
</dependency>
```
@@ -42,7 +42,7 @@ the appropriate dependency version.
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>1.3.0.BUILD-SNAPSHOT</version>
<version>2.0.0.BUILD-SNAPSHOT</version>
</dependency>
<repository>
@@ -52,10 +52,21 @@ the appropriate dependency version.
</repository>
```
###Note:
Spring data elaticsearch until 1.0.0.RELEASE version is on elasticsearch 1.1.x library, which uses java 1.6 or later version.
### Note:
1) Spring data elaticsearch until 1.0.0.RELEASE version is on elasticsearch 1.1.x library, which uses java 1.6 or later version.
2) From spring data elasticsearch 1.1.0.RELEASE the version of elasticsearch is 1.3.x which is supporting java 1.7 or later.
| spring data elasticsearch | elasticsearch |
|:-----------------------------------:|:-------------:|
| 2.0.0.RC1 | 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 |
From spring data elastic search 1.1.0.RELEASE (current) on, the version of elasticsearch 1.3.x is supporting java 1.7 or later.
### ElasticsearchRepository
A default implementation of ElasticsearchRepository, aligning to the generic Repository Interfaces, is provided. Spring can do the Repository implementation for you depending on method names in the interface definition.
@@ -244,4 +255,4 @@ Before we accept a non-trivial patch or pull request we will need you to sign th
Code formatting for [Eclipse and Intellij](https://github.com/spring-projects/spring-data-build/tree/master/etc/ide)
[More information about contributing to Spring Data](https://github.com/spring-projects/spring-data-build/blob/master/CONTRIBUTING.md)
[More information about contributing to Spring Data](https://github.com/spring-projects/spring-data-build/blob/master/CONTRIBUTING.adoc)
+60 -12
View File
@@ -1,15 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>1.3.0.RC1</version>
<version>2.0.6.RELEASE</version>
<parent>
<groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId>
<version>1.7.0.RC1</version>
<version>1.8.6.RELEASE</version>
<relativePath>../spring-data-build/parent/pom.xml</relativePath>
</parent>
@@ -23,8 +23,8 @@
<commonscollections>3.2.1</commonscollections>
<commonslang>2.6</commonslang>
<elasticsearch>1.5.2</elasticsearch>
<springdata.commons>1.11.0.RC1</springdata.commons>
<elasticsearch>2.2.0</elasticsearch>
<springdata.commons>1.12.6.RELEASE</springdata.commons>
</properties>
@@ -60,11 +60,6 @@
<artifactId>commons-lang</artifactId>
<version>${commonslang}</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>${commonscollections}</version>
</dependency>
<!-- JODA Time -->
<dependency>
@@ -113,6 +108,16 @@
<artifactId>cditest-owb</artifactId>
<version>${webbeans}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jcdi_1.0_spec</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-atinject_1.0_spec</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
@@ -121,6 +126,13 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
@@ -138,8 +150,44 @@
<artifactId>asciidoctor-maven-plugin</artifactId>
</plugin>
</plugins>
<testResources>
<testResource>
<directory>${basedir}/src/test/resources</directory>
</testResource>
<testResource>
<targetPath>${basedir}/target/test-home-dir</targetPath>
<directory>${basedir}/src/test/es-modules/${elasticsearch}</directory>
<includes>
<include>**/*</include>
</includes>
</testResource>
</testResources>
</build>
<profiles>
<profile>
<id>es2.3.3</id>
<properties>
<elasticsearch>2.3.3</elasticsearch>
</properties>
</profile>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.jfrog.buildinfo</groupId>
<artifactId>artifactory-maven-plugin</artifactId>
<inherited>false</inherited>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<developers>
<developer>
<id>biomedcentral</id>
@@ -150,8 +198,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>
@@ -30,7 +30,7 @@ public @interface CompletionField {
String searchAnalyzer() default "simple";
String indexAnalyzer() default "simple";
String analyzer() default "simple";
boolean payloads() default false;
@@ -24,6 +24,7 @@ import org.springframework.data.annotation.Persistent;
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Mason Chan
*/
@Persistent
@@ -36,6 +37,8 @@ public @interface Document {
String type() default "";
boolean useServerConfiguration() default false;
short shards() default 5;
short replicas() default 1;
@@ -43,4 +46,6 @@ public @interface Document {
String refreshInterval() default "1s";
String indexStoreType() default "fs";
boolean createIndex() default true;
}
@@ -48,7 +48,7 @@ public @interface Field {
String searchAnalyzer() default "";
String indexAnalyzer() default "";
String analyzer() default "";
String[] ignoreFields() default {};
@@ -21,5 +21,5 @@ package org.springframework.data.elasticsearch.annotations;
* @author Artur Konczak
*/
public enum FieldType {
String, Integer, Long, Date, Float, Double, Boolean, Object, Auto, Nested, Ip
String, Integer, Long, Date, Float, Double, Boolean, Object, Auto, Nested, Ip, Attachment
}
@@ -25,4 +25,8 @@ import java.lang.annotation.*;
@Documented
public @interface GeoPointField {
boolean geoHashPrefix() default false;
String geoHashPrecision() default "0";
}
@@ -25,9 +25,9 @@ import java.lang.annotation.Target;
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface NestedField {
public @interface InnerField {
String dotSuffix();
String suffix();
FieldType type();
@@ -26,7 +26,7 @@ import org.springframework.data.annotation.Persistent;
@Persistent
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Target({ElementType.TYPE, ElementType.FIELD})
public @interface Mapping {
String mappingPath() default "";
@@ -30,5 +30,5 @@ public @interface MultiField {
public Field mainField();
public NestedField[] otherFields() default {};
public InnerField[] otherFields() default {};
}
@@ -0,0 +1,19 @@
package org.springframework.data.elasticsearch.annotations;
import java.lang.annotation.*;
/**
* @author Ryan Murfitt
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
public @interface ScriptedField {
/**
* (Optional) The name of the scripted field. Defaults to
* the field name.
*/
String name() default "";
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* 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.
@@ -17,9 +17,11 @@ 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.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
@@ -40,6 +42,9 @@ public class NodeClientFactoryBean implements FactoryBean<NodeClient>, Initializ
private boolean enableHttp;
private String clusterName;
private NodeClient nodeClient;
private String pathData;
private String pathHome;
private String pathConfiguration;
NodeClientFactoryBean() {
}
@@ -65,13 +70,25 @@ public class NodeClientFactoryBean implements FactoryBean<NodeClient>, Initializ
@Override
public void afterPropertiesSet() throws Exception {
ImmutableSettings.Builder settings = ImmutableSettings.settingsBuilder().put("http.enabled",
String.valueOf(this.enableHttp));
nodeClient = (NodeClient) nodeBuilder().settings(settings).clusterName(this.clusterName).local(this.local).node()
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;
}
@@ -84,6 +101,18 @@ public class NodeClientFactoryBean implements FactoryBean<NodeClient>, Initializ
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 {
@@ -16,8 +16,8 @@
package org.springframework.data.elasticsearch.client;
import static org.apache.commons.lang.StringUtils.*;
import static org.elasticsearch.common.settings.ImmutableSettings.*;
import java.net.InetAddress;
import java.util.Properties;
import org.elasticsearch.client.transport.TransportClient;
@@ -86,24 +86,24 @@ public class TransportClientFactoryBean implements FactoryBean<TransportClient>,
}
protected void buildClient() throws Exception {
client = new TransportClient(settings());
client = TransportClient.builder().settings(settings()).build();
Assert.hasText(clusterNodes, "[Assertion failed] clusterNodes settings missing.");
for (String clusterNode : split(clusterNodes, COMMA)) {
String hostName = substringBefore(clusterNode, COLON);
String port = substringAfter(clusterNode, COLON);
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(hostName, Integer.valueOf(port)));
client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(hostName), Integer.valueOf(port)));
}
client.connectedNodes();
}
private Settings settings() {
if (properties != null) {
return settingsBuilder().put(properties).build();
return Settings.builder().put(properties).build();
}
return settingsBuilder()
return Settings.builder()
.put("cluster.name", clusterName)
.put("client.transport.sniff", clientTransportSniff)
.put("client.transport.ignore_cluster_name", clientIgnoreClusterName)
@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* 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.
@@ -43,6 +43,9 @@ public class NodeClientBeanDefinitionParser extends AbstractBeanDefinitionParser
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,
@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,6 @@
*/
package org.springframework.data.elasticsearch.core;
import static org.elasticsearch.index.query.FilterBuilders.*;
import static org.springframework.data.elasticsearch.core.query.Criteria.*;
import java.util.Iterator;
@@ -23,9 +22,8 @@ import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import org.elasticsearch.index.query.FilterBuilder;
import org.elasticsearch.index.query.GeoBoundingBoxFilterBuilder;
import org.elasticsearch.index.query.GeoDistanceFilterBuilder;
import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.index.query.*;
import org.springframework.data.elasticsearch.core.geo.GeoBox;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.elasticsearch.core.query.Criteria;
@@ -39,24 +37,30 @@ import org.springframework.util.Assert;
* CriteriaFilterProcessor
*
* @author Franck Marchand
* @author Mohsin Husen
* @author Artur Konczak
*
*/
class CriteriaFilterProcessor {
FilterBuilder createFilterFromCriteria(Criteria criteria) {
List<FilterBuilder> fbList = new LinkedList<FilterBuilder>();
FilterBuilder filter = null;
QueryBuilder createFilterFromCriteria(Criteria criteria) {
List<QueryBuilder> fbList = new LinkedList<QueryBuilder>();
QueryBuilder filter = null;
ListIterator<Criteria> chainIterator = criteria.getCriteriaChain().listIterator();
while (chainIterator.hasNext()) {
FilterBuilder fb = null;
QueryBuilder fb = null;
Criteria chainedCriteria = chainIterator.next();
if (chainedCriteria.isOr()) {
fb = orFilter(createFilterFragmentForCriteria(chainedCriteria).toArray(new FilterBuilder[]{}));
fb = QueryBuilders.boolQuery();
for(QueryBuilder f: createFilterFragmentForCriteria(chainedCriteria)){
((BoolQueryBuilder)fb).should(f);
}
fbList.add(fb);
} else if (chainedCriteria.isNegating()) {
List<FilterBuilder> negationFilters = buildNegationFilter(criteria.getField().getName(), criteria.getFilterCriteriaEntries().iterator());
List<QueryBuilder> negationFilters = buildNegationFilter(criteria.getField().getName(), criteria.getFilterCriteriaEntries().iterator());
if (!negationFilters.isEmpty()) {
fbList.addAll(negationFilters);
@@ -70,21 +74,23 @@ class CriteriaFilterProcessor {
if (fbList.size() == 1) {
filter = fbList.get(0);
} else {
filter = andFilter(fbList.toArray(new FilterBuilder[]{}));
filter = QueryBuilders.boolQuery();
for(QueryBuilder f: fbList) {
((BoolQueryBuilder)filter).must(f);
}
}
}
return filter;
}
private List<FilterBuilder> createFilterFragmentForCriteria(Criteria chainedCriteria) {
private List<QueryBuilder> createFilterFragmentForCriteria(Criteria chainedCriteria) {
Iterator<Criteria.CriteriaEntry> it = chainedCriteria.getFilterCriteriaEntries().iterator();
List<FilterBuilder> filterList = new LinkedList<FilterBuilder>();
List<QueryBuilder> filterList = new LinkedList<QueryBuilder>();
String fieldName = chainedCriteria.getField().getName();
Assert.notNull(fieldName, "Unknown field");
FilterBuilder filter = null;
QueryBuilder filter = null;
while (it.hasNext()) {
Criteria.CriteriaEntry entry = it.next();
@@ -96,15 +102,15 @@ class CriteriaFilterProcessor {
}
private FilterBuilder processCriteriaEntry(OperationKey key, Object value, String fieldName) {
private QueryBuilder processCriteriaEntry(OperationKey key, Object value, String fieldName) {
if (value == null) {
return null;
}
FilterBuilder filter = null;
QueryBuilder filter = null;
switch (key) {
case WITHIN: {
filter = geoDistanceFilter(fieldName);
GeoDistanceQueryBuilder geoDistanceQueryBuilder = QueryBuilders.geoDistanceQuery(fieldName);
Assert.isTrue(value instanceof Object[], "Value of a geo distance filter should be an array of two values.");
Object[] valArray = (Object[]) value;
@@ -123,25 +129,26 @@ class CriteriaFilterProcessor {
if (valArray[0] instanceof GeoPoint) {
GeoPoint loc = (GeoPoint) valArray[0];
((GeoDistanceFilterBuilder) filter).lat(loc.getLat()).lon(loc.getLon()).distance(dist.toString());
geoDistanceQueryBuilder.lat(loc.getLat()).lon(loc.getLon()).distance(dist.toString()).geoDistance(GeoDistance.PLANE);
} else if (valArray[0] instanceof Point) {
GeoPoint loc = GeoPoint.fromPoint((Point) valArray[0]);
((GeoDistanceFilterBuilder) filter).lat(loc.getLat()).lon(loc.getLon()).distance(dist.toString());
geoDistanceQueryBuilder.lat(loc.getLat()).lon(loc.getLon()).distance(dist.toString()).geoDistance(GeoDistance.PLANE);
} else {
String loc = (String) valArray[0];
if (loc.contains(",")) {
String c[] = loc.split(",");
((GeoDistanceFilterBuilder) filter).lat(Double.parseDouble(c[0])).lon(Double.parseDouble(c[1])).distance(dist.toString());
geoDistanceQueryBuilder.lat(Double.parseDouble(c[0])).lon(Double.parseDouble(c[1])).distance(dist.toString()).geoDistance(GeoDistance.PLANE);
} else {
((GeoDistanceFilterBuilder) filter).geohash(loc).distance(dist.toString());
geoDistanceQueryBuilder.geohash(loc).distance(dist.toString()).geoDistance(GeoDistance.PLANE);
}
}
filter = geoDistanceQueryBuilder;
break;
}
case BBOX: {
filter = geoBoundingBoxFilter(fieldName);
filter = QueryBuilders.geoBoundingBoxQuery(fieldName);
Assert.isTrue(value instanceof Object[], "Value of a boundedBy filter should be an array of one or two values.");
Object[] valArray = (Object[]) value;
@@ -149,11 +156,11 @@ class CriteriaFilterProcessor {
if (valArray.length == 1) {
//GeoEnvelop
oneParameterBBox((GeoBoundingBoxFilterBuilder) filter, valArray[0]);
oneParameterBBox((GeoBoundingBoxQueryBuilder) filter, valArray[0]);
} else if (valArray.length == 2) {
//2x GeoPoint
//2x String
twoParameterBBox((GeoBoundingBoxFilterBuilder) filter, valArray);
twoParameterBBox((GeoBoundingBoxQueryBuilder) filter, valArray);
} else {
//error
Assert.isTrue(false, "Geo distance filter takes a 1-elements array(GeoBox) or 2-elements array(GeoPoints or Strings(format lat,lon or geohash)).");
@@ -188,7 +195,7 @@ class CriteriaFilterProcessor {
}
}
private void oneParameterBBox(GeoBoundingBoxFilterBuilder filter, Object value) {
private void oneParameterBBox(GeoBoundingBoxQueryBuilder filter, Object value) {
Assert.isTrue(value instanceof GeoBox || value instanceof Box, "single-element of boundedBy filter must be type of GeoBox or Box");
GeoBox geoBBox;
@@ -212,7 +219,7 @@ class CriteriaFilterProcessor {
return true;
}
private void twoParameterBBox(GeoBoundingBoxFilterBuilder filter, Object[] values) {
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)");
if (values[0] instanceof GeoPoint) {
GeoPoint topLeft = (GeoPoint) values[0];
@@ -227,12 +234,12 @@ class CriteriaFilterProcessor {
}
}
private List<FilterBuilder> buildNegationFilter(String fieldName, Iterator<Criteria.CriteriaEntry> it) {
List<FilterBuilder> notFilterList = new LinkedList<FilterBuilder>();
private List<QueryBuilder> buildNegationFilter(String fieldName, Iterator<Criteria.CriteriaEntry> it) {
List<QueryBuilder> notFilterList = new LinkedList<QueryBuilder>();
while (it.hasNext()) {
Criteria.CriteriaEntry criteriaEntry = it.next();
FilterBuilder notFilter = notFilter(processCriteriaEntry(criteriaEntry.getKey(), criteriaEntry.getValue(), fieldName));
QueryBuilder notFilter = QueryBuilders.boolQuery().mustNot(processCriteriaEntry(criteriaEntry.getKey(), criteriaEntry.getValue(), fieldName));
notFilterList.add(notFilter);
}
@@ -24,10 +24,11 @@ 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.geo.GeoPoint;
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.data.geo.Point;
import org.springframework.util.Assert;
/**
@@ -36,6 +37,7 @@ import org.springframework.util.Assert;
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Franck Marchand
* @author Artur Konczak
*/
class CriteriaQueryProcessor {
@@ -49,11 +51,19 @@ class CriteriaQueryProcessor {
List<QueryBuilder> mustQueryBuilderList = new LinkedList<QueryBuilder>();
ListIterator<Criteria> chainIterator = criteria.getCriteriaChain().listIterator();
QueryBuilder firstQuery = null;
boolean negateFirstQuery = false;
while (chainIterator.hasNext()) {
Criteria chainedCriteria = chainIterator.next();
QueryBuilder queryFragmentForCriteria = createQueryFragmentForCriteria(chainedCriteria);
if (queryFragmentForCriteria != null) {
if (firstQuery == null) {
firstQuery = queryFragmentForCriteria;
negateFirstQuery = chainedCriteria.isNegating();
continue;
}
if (chainedCriteria.isOr()) {
shouldQueryBuilderList.add(queryFragmentForCriteria);
} else if (chainedCriteria.isNegating()) {
@@ -64,6 +74,18 @@ class CriteriaQueryProcessor {
}
}
if (firstQuery != null) {
if (!shouldQueryBuilderList.isEmpty() && mustNotQueryBuilderList.isEmpty() && mustQueryBuilderList.isEmpty()) {
shouldQueryBuilderList.add(0, firstQuery);
} else {
if (negateFirstQuery) {
mustNotQueryBuilderList.add(0, firstQuery);
} else {
mustQueryBuilderList.add(0, firstQuery);
}
}
}
BoolQueryBuilder query = null;
if (!shouldQueryBuilderList.isEmpty() || !mustNotQueryBuilderList.isEmpty() || !mustQueryBuilderList.isEmpty()) {
@@ -98,12 +120,12 @@ class CriteriaQueryProcessor {
if (singeEntryCriteria) {
Criteria.CriteriaEntry entry = it.next();
query = processCriteriaEntry(entry.getKey(), entry.getValue(), fieldName);
query = processCriteriaEntry(entry, fieldName);
} else {
query = boolQuery();
while (it.hasNext()) {
Criteria.CriteriaEntry entry = it.next();
((BoolQueryBuilder) query).must(processCriteriaEntry(entry.getKey(), entry.getValue(), fieldName));
((BoolQueryBuilder) query).must(processCriteriaEntry(entry, fieldName));
}
}
@@ -112,46 +134,68 @@ class CriteriaQueryProcessor {
}
private QueryBuilder processCriteriaEntry(OperationKey key, Object value, String fieldName) {
private QueryBuilder processCriteriaEntry(Criteria.CriteriaEntry entry,/* OperationKey key, Object value,*/ String fieldName) {
Object value = entry.getValue();
if (value == null) {
return null;
}
OperationKey key = entry.getKey();
QueryBuilder query = null;
String searchText = StringUtils.toString(value);
Iterable<Object> collection = null;
switch (key) {
case EQUALS:
query = queryString(searchText).field(fieldName).defaultOperator(QueryStringQueryBuilder.Operator.AND);
query = queryStringQuery(searchText).field(fieldName).defaultOperator(QueryStringQueryBuilder.Operator.AND);
break;
case CONTAINS:
query = queryString("*" + searchText + "*").field(fieldName).analyzeWildcard(true);
query = queryStringQuery("*" + searchText + "*").field(fieldName).analyzeWildcard(true);
break;
case STARTS_WITH:
query = queryString(searchText + "*").field(fieldName).analyzeWildcard(true);
query = queryStringQuery(searchText + "*").field(fieldName).analyzeWildcard(true);
break;
case ENDS_WITH:
query = queryString("*" + searchText).field(fieldName).analyzeWildcard(true);
query = queryStringQuery("*" + searchText).field(fieldName).analyzeWildcard(true);
break;
case EXPRESSION:
query = queryString((String) value).field(fieldName);
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, (String) value);
query = fuzzyQuery(fieldName, searchText);
break;
case IN:
query = boolQuery();
Iterable<Object> collection = (Iterable<Object>) value;
collection = (Iterable<Object>) value;
for (Object item : collection) {
((BoolQueryBuilder) query).should(queryString((String) item).field(fieldName));
((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;
}
@@ -16,9 +16,27 @@
package org.springframework.data.elasticsearch.core;
import java.io.IOException;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.core.geo.CustomGeoModule;
import org.springframework.data.geo.*;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* DocumentMapper using jackson
@@ -34,6 +52,7 @@ public class DefaultEntityMapper implements EntityMapper {
objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
objectMapper.registerModule(new CustomGeoModule());
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* Copyright 2014-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,28 +18,28 @@ package org.springframework.data.elasticsearch.core;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.MultiGetItemResponse;
import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.base.Strings;
import org.elasticsearch.common.jackson.core.JsonEncoding;
import org.elasticsearch.common.jackson.core.JsonFactory;
import org.elasticsearch.common.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHitField;
import org.elasticsearch.search.facet.Facet;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.ElasticsearchException;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.core.facet.DefaultFacetMapper;
import org.springframework.data.elasticsearch.core.facet.FacetResult;
import org.springframework.data.elasticsearch.annotations.ScriptedField;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.mapping.PersistentProperty;
@@ -47,6 +47,8 @@ import org.springframework.data.mapping.context.MappingContext;
/**
* @author Artur Konczak
* @author Young Gu
* @author Oliver Gierke
*/
public class DefaultResultMapper extends AbstractResultMapper {
@@ -73,35 +75,50 @@ public class DefaultResultMapper extends AbstractResultMapper {
}
@Override
public <T> FacetedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
public <T> Page<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
long totalHits = response.getHits().totalHits();
List<T> results = new ArrayList<T>();
for (SearchHit hit : response.getHits()) {
if (hit != null) {
T result = null;
if (!Strings.isNullOrEmpty(hit.sourceAsString())) {
if (StringUtils.isNotBlank(hit.sourceAsString())) {
result = mapEntity(hit.sourceAsString(), clazz);
} else {
result = mapEntity(hit.getFields().values(), clazz);
}
setPersistentEntityId(result, hit.getId(), clazz);
populateScriptFields(result, hit);
results.add(result);
}
}
List<FacetResult> facets = new ArrayList<FacetResult>();
if (response.getFacets() != null) {
for (Facet facet : response.getFacets()) {
FacetResult facetResult = DefaultFacetMapper.parse(facet);
if (facetResult != null) {
facets.add(facetResult);
}
}
}
return new FacetedPageImpl<T>(results, pageable, totalHits, facets);
return new PageImpl<T>(results, pageable, totalHits);
}
private <T> T mapEntity(Collection<SearchHitField> values, Class<T> clazz) {
private <T> void populateScriptFields(T result, SearchHit hit) {
if (hit.getFields() != null && !hit.getFields().isEmpty() && result != null) {
for (java.lang.reflect.Field field : result.getClass().getDeclaredFields()) {
ScriptedField scriptedField = field.getAnnotation(ScriptedField.class);
if (scriptedField != null) {
String name = scriptedField.name().isEmpty() ? field.getName() : scriptedField.name();
SearchHitField searchHitField = hit.getFields().get(name);
if (searchHitField != null) {
field.setAccessible(true);
try {
field.set(result, searchHitField.getValue());
} catch (IllegalArgumentException e) {
throw new ElasticsearchException("failed to set scripted field: " + name + " with value: "
+ searchHitField.getValue(), e);
} catch (IllegalAccessException e) {
throw new ElasticsearchException("failed to access scripted field: " + name, e);
}
}
}
}
}
}
private <T> T mapEntity(Collection<SearchHitField> values, Class<T> clazz) {
return mapEntity(buildJSONFromFields(values), clazz);
}
@@ -153,18 +170,15 @@ public class DefaultResultMapper extends AbstractResultMapper {
}
private <T> void setPersistentEntityId(T result, String id, Class<T> clazz) {
if (mappingContext != null && clazz.isAnnotationPresent(Document.class)) {
PersistentProperty<ElasticsearchPersistentProperty> idProperty = mappingContext.getPersistentEntity(clazz).getIdProperty();
ElasticsearchPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(clazz);
PersistentProperty<?> idProperty = persistentEntity.getIdProperty();
// Only deal with String because ES generated Ids are strings !
if (idProperty != null && idProperty.getType().isAssignableFrom(String.class)) {
Method setter = idProperty.getSetter();
if (setter != null) {
try {
setter.invoke(result, id);
} catch (Throwable t) {
t.printStackTrace();
}
}
persistentEntity.getPropertyAccessor(result).setProperty(idProperty, id);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors.
* Copyright 2013-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,15 +16,17 @@
package org.springframework.data.elasticsearch.core;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.springframework.data.domain.Page;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.data.util.CloseableIterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* ElasticsearchOperations
@@ -40,6 +42,11 @@ public interface ElasticsearchOperations {
*/
ElasticsearchConverter getElasticsearchConverter();
/**
* @return elasticsearch client
*/
Client getClient();
/**
* Create an index for a class
*
@@ -172,7 +179,7 @@ public interface ElasticsearchOperations {
* @param clazz
* @return
*/
<T> FacetedPage<T> queryForPage(SearchQuery query, Class<T> clazz);
<T> Page<T> queryForPage(SearchQuery query, Class<T> clazz);
/**
* Execute the query against elasticsearch and return result as {@link Page} using custom mapper
@@ -181,7 +188,7 @@ public interface ElasticsearchOperations {
* @param clazz
* @return
*/
<T> FacetedPage<T> queryForPage(SearchQuery query, Class<T> clazz, SearchResultMapper mapper);
<T> Page<T> queryForPage(SearchQuery query, Class<T> clazz, SearchResultMapper mapper);
/**
* Execute the query against elasticsearch and return result as {@link Page}
@@ -199,7 +206,7 @@ public interface ElasticsearchOperations {
* @param clazz
* @return
*/
<T> FacetedPage<T> queryForPage(StringQuery query, Class<T> clazz);
<T> Page<T> queryForPage(StringQuery query, Class<T> clazz);
/**
* Execute the query against elasticsearch and return result as {@link Page} using custom mapper
@@ -208,7 +215,7 @@ public interface ElasticsearchOperations {
* @param clazz
* @return
*/
<T> FacetedPage<T> queryForPage(StringQuery query, Class<T> clazz, SearchResultMapper mapper);
<T> Page<T> queryForPage(StringQuery query, Class<T> clazz, SearchResultMapper mapper);
/**
* Executes the given {@link CriteriaQuery} against elasticsearch and return result as {@link CloseableIterator}.
@@ -430,14 +437,6 @@ public interface ElasticsearchOperations {
*/
boolean deleteIndex(String indexName);
/**
* Deletes a type in an index
*
* @param index
* @param type
*/
void deleteType(String index, String type);
/**
* check if index is exists
*
@@ -468,38 +467,70 @@ public interface ElasticsearchOperations {
* refresh the index
*
* @param indexName
* @param waitForOperation
*
*/
void refresh(String indexName, boolean waitForOperation);
void refresh(String indexName);
/**
* refresh the index
*
* @param clazz
* @param waitForOperation
*
*/
<T> void refresh(Class<T> clazz, boolean waitForOperation);
<T> void refresh(Class<T> clazz);
/**
* Returns scroll id for criteria query
*
* @param query
* @param scrollTimeInMillis
* @param noFields
* @return
* @param query The criteria query.
* @param scrollTimeInMillis The time in millisecond for scroll feature
* {@link org.elasticsearch.action.search.SearchRequestBuilder#setScroll(org.elasticsearch.common.unit.TimeValue)}.
* @param noFields The no fields support
* {@link org.elasticsearch.action.search.SearchRequestBuilder#setNoFields()}.
* @return The scan id for input query.
*/
String scan(CriteriaQuery query, long scrollTimeInMillis, boolean noFields);
/**
* Returns scroll id for criteria query
*
* @param query The criteria query.
* @param scrollTimeInMillis The time in millisecond for scroll feature
* {@link org.elasticsearch.action.search.SearchRequestBuilder#setScroll(org.elasticsearch.common.unit.TimeValue)}.
* @param noFields The no fields support
* {@link org.elasticsearch.action.search.SearchRequestBuilder#setNoFields()}.
* @param clazz The class of entity to retrieve.
* @param <T> The type of entity to retrieve.
* @return The scan id for input query.
*/
<T> String scan(CriteriaQuery query, long scrollTimeInMillis, boolean noFields, Class<T> clazz);
/**
* Returns scroll id for scan query
*
* @param query
* @param scrollTimeInMillis
* @param noFields
* @return
* @param query The search query.
* @param scrollTimeInMillis The time in millisecond for scroll feature
* {@link org.elasticsearch.action.search.SearchRequestBuilder#setScroll(org.elasticsearch.common.unit.TimeValue)}.
* @param noFields The no fields support
* {@link org.elasticsearch.action.search.SearchRequestBuilder#setNoFields()}.
* @return The scan id for input query.
*/
String scan(SearchQuery query, long scrollTimeInMillis, boolean noFields);
/**
* Returns scroll id for scan query
*
* @param query The search query.
* @param scrollTimeInMillis The time in millisecond for scroll feature
* {@link org.elasticsearch.action.search.SearchRequestBuilder#setScroll(org.elasticsearch.common.unit.TimeValue)}.
* @param noFields The no fields support
* {@link org.elasticsearch.action.search.SearchRequestBuilder#setNoFields()}.
* @param clazz The class of entity to retrieve.
* @param <T> The type of entity to retrieve.
* @return The scan id for input query.
*/
<T> String scan(SearchQuery query, long scrollTimeInMillis, boolean noFields, Class<T> clazz);
/**
* Scrolls the results for give scroll id
*
@@ -522,6 +553,14 @@ public interface ElasticsearchOperations {
*/
<T> Page<T> scroll(String scrollId, long scrollTimeInMillis, SearchResultMapper mapper);
/**
* Clears the search contexts associated with specified scroll ids.
*
* @param scrollId
*
*/
<T> void clearScroll(String scrollId);
/**
* more like this query to search for documents that are "like" a specific document.
*
@@ -554,8 +593,11 @@ public interface ElasticsearchOperations {
* @param indexName
* @return
*/
Set<String> queryForAlias(String indexName);
List<AliasMetaData> queryForAlias(String indexName);
<T> T query(SearchQuery query, ResultsExtractor<T> resultsExtractor);
ElasticsearchPersistentEntity getPersistentEntityFor(Class clazz);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors.
* Copyright 2013-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,12 +15,25 @@
*/
package org.springframework.data.elasticsearch.core;
import org.apache.commons.collections.CollectionUtils;
import static org.apache.commons.lang.StringUtils.isNotBlank;
import static org.apache.commons.lang.StringUtils.isBlank;
import static org.elasticsearch.action.search.SearchType.*;
import static org.elasticsearch.client.Requests.*;
import static org.elasticsearch.cluster.metadata.AliasAction.Type.*;
import static org.elasticsearch.index.VersionType.*;
import static org.elasticsearch.index.query.QueryBuilders.*;
import static org.springframework.data.elasticsearch.core.MappingBuilder.*;
import static org.springframework.util.CollectionUtils.isEmpty;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import org.elasticsearch.action.ListenableActionFuture;
import org.elasticsearch.action.admin.cluster.state.ClusterStateRequest;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.mapping.delete.DeleteMappingRequest;
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequestBuilder;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
@@ -33,7 +46,6 @@ import org.elasticsearch.action.get.MultiGetRequest;
import org.elasticsearch.action.get.MultiGetRequestBuilder;
import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.mlt.MoreLikeThisRequestBuilder;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
@@ -44,17 +56,15 @@ import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.Requests;
import org.elasticsearch.cluster.metadata.AliasAction;
import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.common.collect.ImmutableOpenMap;
import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.elasticsearch.common.collect.MapBuilder;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.query.FilterBuilder;
import org.elasticsearch.index.query.MoreLikeThisQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.facet.FacetBuilder;
import org.elasticsearch.search.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortOrder;
@@ -65,15 +75,13 @@ import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.*;
import org.springframework.data.elasticsearch.ElasticsearchException;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Mapping;
import org.springframework.data.elasticsearch.annotations.Setting;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import org.springframework.data.elasticsearch.core.query.*;
@@ -81,23 +89,6 @@ import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.util.CloseableIterator;
import org.springframework.util.Assert;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.util.*;
import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
import static org.apache.commons.lang.StringUtils.isBlank;
import static org.apache.commons.lang.StringUtils.isNotBlank;
import static org.elasticsearch.action.search.SearchType.SCAN;
import static org.elasticsearch.client.Requests.indicesExistsRequest;
import static org.elasticsearch.client.Requests.refreshRequest;
import static org.elasticsearch.cluster.metadata.AliasAction.Type.ADD;
import static org.elasticsearch.common.collect.Sets.newHashSet;
import static org.elasticsearch.index.VersionType.EXTERNAL;
import static org.springframework.data.elasticsearch.core.MappingBuilder.buildMapping;
/**
* ElasticsearchTemplate
*
@@ -105,6 +96,9 @@ import static org.springframework.data.elasticsearch.core.MappingBuilder.buildMa
* @author Mohsin Husen
* @author Artur Konczak
* @author Kevin Leturc
* @author Mason Chan
* @author Young Gu
* @author Oliver Gierke
*/
public class ElasticsearchTemplate implements ElasticsearchOperations, ApplicationContextAware {
@@ -116,26 +110,39 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
private String searchTimeout;
public ElasticsearchTemplate(Client client) {
this(client, null, null);
this(client, new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext()));
}
public ElasticsearchTemplate(Client client, EntityMapper entityMapper) {
this(client, null, new DefaultResultMapper(entityMapper));
this(client, new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext()), entityMapper);
}
public ElasticsearchTemplate(Client client, ElasticsearchConverter elasticsearchConverter, EntityMapper entityMapper) {
this(client, elasticsearchConverter, new DefaultResultMapper(elasticsearchConverter.getMappingContext(), entityMapper));
}
public ElasticsearchTemplate(Client client, ResultsMapper resultsMapper) {
this(client, null, resultsMapper);
this(client, new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext()), resultsMapper);
}
public ElasticsearchTemplate(Client client, ElasticsearchConverter elasticsearchConverter) {
this(client, elasticsearchConverter, null);
this(client, elasticsearchConverter, new DefaultResultMapper(elasticsearchConverter.getMappingContext()));
}
public ElasticsearchTemplate(Client client, ElasticsearchConverter elasticsearchConverter, ResultsMapper resultsMapper) {
Assert.notNull(client, "Client must not be null!");
Assert.notNull(elasticsearchConverter, "ElasticsearchConverter must not be null!");
Assert.notNull(resultsMapper, "ResultsMapper must not be null!");
this.client = client;
this.elasticsearchConverter = (elasticsearchConverter == null) ? new MappingElasticsearchConverter(
new SimpleElasticsearchMappingContext()) : elasticsearchConverter;
this.resultsMapper = (resultsMapper == null) ? new DefaultResultMapper(this.elasticsearchConverter.getMappingContext()) : resultsMapper;
this.elasticsearchConverter = elasticsearchConverter;
this.resultsMapper = resultsMapper;
}
@Override
public Client getClient() {
return client;
}
public void setSearchTimeout(String searchTimeout) {
@@ -255,12 +262,12 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
}
@Override
public <T> FacetedPage<T> queryForPage(SearchQuery query, Class<T> clazz) {
public <T> Page<T> queryForPage(SearchQuery query, Class<T> clazz) {
return queryForPage(query, clazz, resultsMapper);
}
@Override
public <T> FacetedPage<T> queryForPage(SearchQuery query, Class<T> clazz, SearchResultMapper mapper) {
public <T> Page<T> queryForPage(SearchQuery query, Class<T> clazz, SearchResultMapper mapper) {
SearchResponse response = doSearch(prepareSearch(query, clazz), query);
return mapper.mapResults(response, clazz, query.getPageable());
}
@@ -299,7 +306,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
@Override
public <T> Page<T> queryForPage(CriteriaQuery criteriaQuery, Class<T> clazz) {
QueryBuilder elasticsearchQuery = new CriteriaQueryProcessor().createQueryFromCriteria(criteriaQuery.getCriteria());
FilterBuilder elasticsearchFilter = new CriteriaFilterProcessor().createFilterFromCriteria(criteriaQuery.getCriteria());
QueryBuilder elasticsearchFilter = new CriteriaFilterProcessor().createFilterFromCriteria(criteriaQuery.getCriteria());
SearchRequestBuilder searchRequestBuilder = prepareSearch(criteriaQuery, clazz);
if (elasticsearchQuery != null) {
@@ -314,6 +321,9 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
if (elasticsearchFilter != null)
searchRequestBuilder.setPostFilter(elasticsearchFilter);
if (logger.isDebugEnabled()) {
logger.debug("doSearch query:\n" + searchRequestBuilder.toString());
}
SearchResponse response = getSearchResponse(searchRequestBuilder
.execute());
@@ -321,12 +331,12 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
}
@Override
public <T> FacetedPage<T> queryForPage(StringQuery query, Class<T> clazz) {
public <T> Page<T> queryForPage(StringQuery query, Class<T> clazz) {
return queryForPage(query, clazz, resultsMapper);
}
@Override
public <T> FacetedPage<T> queryForPage(StringQuery query, Class<T> clazz, SearchResultMapper mapper) {
public <T> Page<T> queryForPage(StringQuery query, Class<T> clazz, SearchResultMapper mapper) {
SearchResponse response = getSearchResponse(prepareSearch(query, clazz).setQuery(query.getSource()).execute());
return mapper.mapResults(response, clazz, query.getPageable());
}
@@ -334,7 +344,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
@Override
public <T> CloseableIterator<T> stream(CriteriaQuery query, Class<T> clazz) {
final long scrollTimeInMillis = TimeValue.timeValueMinutes(1).millis();
final String initScrollId = scan(query, scrollTimeInMillis, false);
final String initScrollId = scan(query, scrollTimeInMillis, false, clazz);
return doStream(initScrollId, scrollTimeInMillis, clazz, resultsMapper);
}
@@ -346,7 +356,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
@Override
public <T> CloseableIterator<T> stream(SearchQuery query, final Class<T> clazz, final SearchResultMapper mapper) {
final long scrollTimeInMillis = TimeValue.timeValueMinutes(1).millis();
final String initScrollId = scan(query, scrollTimeInMillis, false);
final String initScrollId = scan(query, scrollTimeInMillis, false, clazz);
return doStream(initScrollId, scrollTimeInMillis, clazz, mapper);
}
@@ -401,14 +411,13 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
}
throw new NoSuchElementException();
}
};
}
@Override
public <T> long count(CriteriaQuery criteriaQuery, Class<T> clazz) {
QueryBuilder elasticsearchQuery = new CriteriaQueryProcessor().createQueryFromCriteria(criteriaQuery.getCriteria());
FilterBuilder elasticsearchFilter = new CriteriaFilterProcessor().createFilterFromCriteria(criteriaQuery.getCriteria());
QueryBuilder elasticsearchFilter = new CriteriaFilterProcessor().createFilterFromCriteria(criteriaQuery.getCriteria());
if (elasticsearchFilter == null) {
return doCount(prepareCount(criteriaQuery, clazz), elasticsearchQuery);
@@ -421,7 +430,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
@Override
public <T> long count(SearchQuery searchQuery, Class<T> clazz) {
QueryBuilder elasticsearchQuery = searchQuery.getQuery();
FilterBuilder elasticsearchFilter = searchQuery.getFilter();
QueryBuilder elasticsearchFilter = searchQuery.getFilter();
if (elasticsearchFilter == null) {
return doCount(prepareCount(searchQuery, clazz), elasticsearchQuery);
@@ -448,7 +457,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
return countRequestBuilder.execute().actionGet().getCount();
}
private long doCount(SearchRequestBuilder searchRequestBuilder, QueryBuilder elasticsearchQuery, FilterBuilder elasticsearchFilter) {
private long doCount(SearchRequestBuilder searchRequestBuilder, QueryBuilder elasticsearchQuery, QueryBuilder elasticsearchFilter) {
if (elasticsearchQuery != null) {
searchRequestBuilder.setQuery(elasticsearchQuery);
} else {
@@ -462,8 +471,8 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
}
private <T> CountRequestBuilder prepareCount(Query query, Class<T> clazz) {
String indexName[] = isNotEmpty(query.getIndices()) ? query.getIndices().toArray(new String[query.getIndices().size()]) : retrieveIndexNameFromPersistentEntity(clazz);
String types[] = isNotEmpty(query.getTypes()) ? query.getTypes().toArray(new String[query.getTypes().size()]) : retrieveTypeFromPersistentEntity(clazz);
String indexName[] = !isEmpty(query.getIndices()) ? query.getIndices().toArray(new String[query.getIndices().size()]) : retrieveIndexNameFromPersistentEntity(clazz);
String types[] = !isEmpty(query.getTypes()) ? query.getTypes().toArray(new String[query.getTypes().size()]) : retrieveTypeFromPersistentEntity(clazz);
Assert.notNull(indexName, "No index defined for Query");
@@ -482,8 +491,8 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
private <T> MultiGetResponse getMultiResponse(Query searchQuery, Class<T> clazz) {
String indexName = isNotEmpty(searchQuery.getIndices()) ? searchQuery.getIndices().get(0) : getPersistentEntityFor(clazz).getIndexName();
String type = isNotEmpty(searchQuery.getTypes()) ? searchQuery.getTypes().get(0) : getPersistentEntityFor(clazz).getIndexType();
String indexName = !isEmpty(searchQuery.getIndices()) ? searchQuery.getIndices().get(0) : getPersistentEntityFor(clazz).getIndexName();
String type = !isEmpty(searchQuery.getTypes()) ? searchQuery.getTypes().get(0) : getPersistentEntityFor(clazz).getIndexType();
Assert.notNull(indexName, "No index defined for Query");
Assert.notNull(type, "No type define for Query");
@@ -535,8 +544,9 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
Assert.notNull(query.getId(), "No Id define for Query");
Assert.notNull(query.getUpdateRequest(), "No IndexRequest define for Query");
UpdateRequestBuilder updateRequestBuilder = client.prepareUpdate(indexName, type, query.getId());
updateRequestBuilder.setRouting(query.getUpdateRequest().routing());
if(query.getUpdateRequest().script() == null) {
if (query.getUpdateRequest().script() == null) {
// doc
if (query.DoUpsert()) {
updateRequestBuilder.setDocAsUpsert(true)
@@ -546,10 +556,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
}
} else {
// or script
updateRequestBuilder
.setScript(query.getUpdateRequest().script(), query.getUpdateRequest().scriptType())
.setScriptParams(query.getUpdateRequest().scriptParams())
.setScriptLang(query.getUpdateRequest().scriptLang());
updateRequestBuilder.setScript(query.getUpdateRequest().script());
}
return updateRequestBuilder;
@@ -608,7 +615,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
@Override
public boolean typeExists(String index, String type) {
return client.admin().cluster().prepareState().execute().actionGet()
.getState().metaData().index(index).mappings().containsKey(type);
.getState().metaData().index(index).getMappings().containsKey(type);
}
@Override
@@ -625,15 +632,6 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
return false;
}
@Override
public void deleteType(String index, String type) {
ImmutableOpenMap<String, MappingMetaData> mappings = client.admin().cluster().prepareState().execute().actionGet()
.getState().metaData().index(index).mappings();
if (mappings.containsKey(type)) {
client.admin().indices().deleteMapping(new DeleteMappingRequest(index).types(type)).actionGet();
}
}
@Override
public String delete(String indexName, String type, String id) {
return client.prepareDelete(indexName, type, id).execute().actionGet().getId();
@@ -647,17 +645,61 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
@Override
public <T> void delete(DeleteQuery deleteQuery, Class<T> clazz) {
ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(clazz);
client.prepareDeleteByQuery(persistentEntity.getIndexName()).setTypes(persistentEntity.getIndexType())
.setQuery(deleteQuery.getQuery()).execute().actionGet();
String indexName = isNotBlank(deleteQuery.getIndex()) ? deleteQuery.getIndex() : getPersistentEntityFor(clazz).getIndexName();
String typeName = isNotBlank(deleteQuery.getType()) ? deleteQuery.getType() : getPersistentEntityFor(clazz).getIndexType();
Integer pageSize = deleteQuery.getPageSize() != null ? deleteQuery.getPageSize() : 1000;
Long scrollTimeInMillis = deleteQuery.getScrollTimeInMillis() != null ? deleteQuery.getScrollTimeInMillis() : 10000l;
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(deleteQuery.getQuery())
.withIndices(indexName)
.withTypes(typeName)
.withPageable(new PageRequest(0, pageSize))
.build();
String scrollId = scan(searchQuery, scrollTimeInMillis, true);
BulkRequestBuilder bulkRequestBuilder = client.prepareBulk();
List<String> ids = new ArrayList<String>();
boolean hasRecords = true;
while (hasRecords) {
Page<String> page = scroll(scrollId, scrollTimeInMillis, new SearchResultMapper() {
@Override
public <T> Page<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
List<String> result = new ArrayList<String>();
for (SearchHit searchHit : response.getHits()) {
String id = searchHit.getId();
result.add(id);
}
if (result.size() > 0) {
return new PageImpl<T>((List<T>) result);
}
return null;
}
});
if (page != null && page.getContent().size() > 0) {
ids.addAll(page.getContent());
} else {
hasRecords = false;
}
}
for(String id : ids) {
bulkRequestBuilder.add(client.prepareDelete(indexName, typeName, id));
}
if(bulkRequestBuilder.numberOfActions() > 0) {
bulkRequestBuilder.execute().actionGet();
}
clearScroll(scrollId);
}
@Override
public void delete(DeleteQuery deleteQuery) {
Assert.notNull(deleteQuery.getIndex(), "No index defined for Query");
Assert.notNull(deleteQuery.getType(), "No type define for Query");
client.prepareDeleteByQuery(deleteQuery.getIndex()).setTypes(deleteQuery.getType())
.setQuery(deleteQuery.getQuery()).execute().actionGet();
delete(deleteQuery, null);
}
@Override
@@ -671,13 +713,52 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
@Override
public String scan(CriteriaQuery criteriaQuery, long scrollTimeInMillis, boolean noFields) {
return doScan(prepareScan(criteriaQuery, scrollTimeInMillis, noFields), criteriaQuery);
}
@Override
public <T> String scan(CriteriaQuery criteriaQuery, long scrollTimeInMillis, boolean noFields, Class<T> clazz) {
return doScan(prepareScan(criteriaQuery, scrollTimeInMillis, noFields, clazz), criteriaQuery);
}
@Override
public String scan(SearchQuery searchQuery, long scrollTimeInMillis, boolean noFields) {
return doScan(prepareScan(searchQuery, scrollTimeInMillis, noFields), searchQuery);
}
@Override
public <T> String scan(SearchQuery searchQuery, long scrollTimeInMillis, boolean noFields, Class<T> clazz) {
return doScan(prepareScan(searchQuery, scrollTimeInMillis, noFields, clazz), searchQuery);
}
private <T> SearchRequestBuilder prepareScan(Query query, long scrollTimeInMillis, boolean noFields, Class<T> clazz) {
setPersistentEntityIndexAndType(query, clazz);
return prepareScan(query, scrollTimeInMillis, noFields);
}
private SearchRequestBuilder prepareScan(Query query, long scrollTimeInMillis, boolean noFields) {
SearchRequestBuilder requestBuilder = client.prepareSearch(toArray(query.getIndices())).setSearchType(SCAN)
.setTypes(toArray(query.getTypes()))
.setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)).setFrom(0)
.setSize(query.getPageable().getPageSize());
if (!isEmpty(query.getFields())) {
requestBuilder.addFields(toArray(query.getFields()));
}
if (noFields) {
requestBuilder.setNoFields();
}
return requestBuilder;
}
private String doScan(SearchRequestBuilder requestBuilder, CriteriaQuery criteriaQuery) {
Assert.notNull(criteriaQuery.getIndices(), "No index defined for Query");
Assert.notNull(criteriaQuery.getTypes(), "No type define for Query");
Assert.notNull(criteriaQuery.getPageable(), "Query.pageable is required for scan & scroll");
QueryBuilder elasticsearchQuery = new CriteriaQueryProcessor().createQueryFromCriteria(criteriaQuery.getCriteria());
FilterBuilder elasticsearchFilter = new CriteriaFilterProcessor().createFilterFromCriteria(criteriaQuery.getCriteria());
SearchRequestBuilder requestBuilder = prepareScan(criteriaQuery, scrollTimeInMillis, noFields);
QueryBuilder elasticsearchFilter = new CriteriaFilterProcessor().createFilterFromCriteria(criteriaQuery.getCriteria());
if (elasticsearchQuery != null) {
requestBuilder.setQuery(elasticsearchQuery);
@@ -692,14 +773,11 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
return getSearchResponse(requestBuilder.execute()).getScrollId();
}
@Override
public String scan(SearchQuery searchQuery, long scrollTimeInMillis, boolean noFields) {
private String doScan(SearchRequestBuilder requestBuilder, SearchQuery searchQuery) {
Assert.notNull(searchQuery.getIndices(), "No index defined for Query");
Assert.notNull(searchQuery.getTypes(), "No type define for Query");
Assert.notNull(searchQuery.getPageable(), "Query.pageable is required for scan & scroll");
SearchRequestBuilder requestBuilder = prepareScan(searchQuery, scrollTimeInMillis, noFields);
if (searchQuery.getFilter() != null) {
requestBuilder.setPostFilter(searchQuery.getFilter());
}
@@ -707,22 +785,6 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
return getSearchResponse(requestBuilder.setQuery(searchQuery.getQuery()).execute()).getScrollId();
}
private SearchRequestBuilder prepareScan(Query query, long scrollTimeInMillis, boolean noFields) {
SearchRequestBuilder requestBuilder = client.prepareSearch(toArray(query.getIndices())).setSearchType(SCAN)
.setTypes(toArray(query.getTypes()))
.setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)).setFrom(0)
.setSize(query.getPageable().getPageSize());
if (isNotEmpty(query.getFields())) {
requestBuilder.addFields(toArray(query.getFields()));
}
if (noFields) {
requestBuilder.setNoFields();
}
return requestBuilder;
}
@Override
public <T> Page<T> scroll(String scrollId, long scrollTimeInMillis, Class<T> clazz) {
SearchResponse response = getSearchResponse(client.prepareSearchScroll(scrollId)
@@ -737,9 +799,14 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
return mapper.mapResults(response, null, null);
}
@Override
public void clearScroll(String scrollId) {
client.prepareClearScroll().addScrollId(scrollId).execute().actionGet();
}
@Override
public <T> Page<T> moreLikeThis(MoreLikeThisQuery query, Class<T> clazz) {
int startRecord = 0;
ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(clazz);
String indexName = isNotBlank(query.getIndexName()) ? query.getIndexName() : persistentEntity.getIndexName();
String type = isNotBlank(query.getType()) ? query.getType() : persistentEntity.getIndexType();
@@ -748,56 +815,35 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
Assert.notNull(type, "No 'type' defined for MoreLikeThisQuery");
Assert.notNull(query.getId(), "No document id defined for MoreLikeThisQuery");
MoreLikeThisRequestBuilder requestBuilder = client.prepareMoreLikeThis(indexName, type, query.getId());
MoreLikeThisQueryBuilder moreLikeThisQueryBuilder = moreLikeThisQuery()
.addLikeItem(new MoreLikeThisQueryBuilder.Item(indexName, type, query.getId()));
if (query.getPageable() != null) {
startRecord = query.getPageable().getPageNumber() * query.getPageable().getPageSize();
requestBuilder.setSearchSize(query.getPageable().getPageSize());
}
requestBuilder.setSearchFrom(startRecord);
if (isNotEmpty(query.getSearchIndices())) {
requestBuilder.setSearchIndices(toArray(query.getSearchIndices()));
}
if (isNotEmpty(query.getSearchTypes())) {
requestBuilder.setSearchTypes(toArray(query.getSearchTypes()));
}
if (isNotEmpty(query.getFields())) {
requestBuilder.setField(toArray(query.getFields()));
}
if (isNotBlank(query.getRouting())) {
requestBuilder.setRouting(query.getRouting());
}
if (query.getPercentTermsToMatch() != null) {
requestBuilder.setPercentTermsToMatch(query.getPercentTermsToMatch());
}
if (query.getMinTermFreq() != null) {
requestBuilder.setMinTermFreq(query.getMinTermFreq());
moreLikeThisQueryBuilder.minTermFreq(query.getMinTermFreq());
}
if (query.getMaxQueryTerms() != null) {
requestBuilder.maxQueryTerms(query.getMaxQueryTerms());
moreLikeThisQueryBuilder.maxQueryTerms(query.getMaxQueryTerms());
}
if (isNotEmpty(query.getStopWords())) {
requestBuilder.setStopWords(toArray(query.getStopWords()));
if (!isEmpty(query.getStopWords())) {
moreLikeThisQueryBuilder.stopWords(toArray(query.getStopWords()));
}
if (query.getMinDocFreq() != null) {
requestBuilder.setMinDocFreq(query.getMinDocFreq());
moreLikeThisQueryBuilder.minDocFreq(query.getMinDocFreq());
}
if (query.getMaxDocFreq() != null) {
requestBuilder.setMaxDocFreq(query.getMaxDocFreq());
moreLikeThisQueryBuilder.maxDocFreq(query.getMaxDocFreq());
}
if (query.getMinWordLen() != null) {
requestBuilder.setMinWordLen(query.getMinWordLen());
moreLikeThisQueryBuilder.minWordLength(query.getMinWordLen());
}
if (query.getMaxWordLen() != null) {
requestBuilder.setMaxWordLen(query.getMaxWordLen());
moreLikeThisQueryBuilder.maxWordLength(query.getMaxWordLen());
}
if (query.getBoostTerms() != null) {
requestBuilder.setBoostTerms(query.getBoostTerms());
moreLikeThisQueryBuilder.boostTerms(query.getBoostTerms());
}
SearchResponse response = getSearchResponse(requestBuilder.execute());
return resultsMapper.mapResults(response, clazz, query.getPageable());
return queryForPage(new NativeSearchQueryBuilder().withQuery(moreLikeThisQueryBuilder).build(), clazz);
}
private SearchResponse doSearch(SearchRequestBuilder searchRequest, SearchQuery searchQuery) {
@@ -805,19 +851,16 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
searchRequest.setPostFilter(searchQuery.getFilter());
}
if (CollectionUtils.isNotEmpty(searchQuery.getElasticsearchSorts())) {
if (!isEmpty(searchQuery.getElasticsearchSorts())) {
for (SortBuilder sort : searchQuery.getElasticsearchSorts()) {
searchRequest.addSort(sort);
}
}
if (CollectionUtils.isNotEmpty(searchQuery.getFacets())) {
for (FacetRequest facetRequest : searchQuery.getFacets()) {
FacetBuilder facet = facetRequest.getFacet();
if (facetRequest.applyQueryFilter() && searchQuery.getFilter() != null) {
facet.facetFilter(searchQuery.getFilter());
}
searchRequest.addFacet(facet);
if (!searchQuery.getScriptFields().isEmpty()) {
searchRequest.addField("_source");
for (ScriptField scriptedField : searchQuery.getScriptFields()) {
searchRequest.addScriptField(scriptedField.fieldName(), scriptedField.script());
}
}
@@ -827,7 +870,13 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
}
}
if (CollectionUtils.isNotEmpty(searchQuery.getAggregations())) {
if (!isEmpty(searchQuery.getIndicesBoost())) {
for (IndexBoost indexBoost : searchQuery.getIndicesBoost()) {
searchRequest.addIndexBoost(indexBoost.getIndexName(), indexBoost.getBoost());
}
}
if (!isEmpty(searchQuery.getAggregations())) {
for (AbstractAggregationBuilder aggregationBuilder : searchQuery.getAggregations()) {
searchRequest.addAggregation(aggregationBuilder);
}
@@ -877,6 +926,10 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
}
private <T> Map getDefaultSettings(ElasticsearchPersistentEntity<T> persistentEntity) {
if (persistentEntity.isUseServerConfiguration())
return new HashMap();
return new MapBuilder<String, String>().put("index.number_of_shards", String.valueOf(persistentEntity.getShards()))
.put("index.number_of_replicas", String.valueOf(persistentEntity.getReplicas()))
.put("index.refresh_interval", persistentEntity.getRefreshInterval())
@@ -896,12 +949,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
}
private <T> SearchRequestBuilder prepareSearch(Query query, Class<T> clazz) {
if (query.getIndices().isEmpty()) {
query.addIndices(retrieveIndexNameFromPersistentEntity(clazz));
}
if (query.getTypes().isEmpty()) {
query.addTypes(retrieveTypeFromPersistentEntity(clazz));
}
setPersistentEntityIndexAndType(query, clazz);
return prepareSearch(query);
}
@@ -913,6 +961,11 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
SearchRequestBuilder searchRequestBuilder = client.prepareSearch(toArray(query.getIndices()))
.setSearchType(query.getSearchType()).setTypes(toArray(query.getTypes()));
if (query.getSourceFilter() != null) {
SourceFilter sourceFilter = query.getSourceFilter();
searchRequestBuilder.setFetchSource(sourceFilter.getIncludes(), sourceFilter.getExcludes());
}
if (query.getPageable() != null) {
startRecord = query.getPageable().getPageNumber() * query.getPageable().getPageSize();
searchRequestBuilder.setSize(query.getPageable().getPageSize());
@@ -978,15 +1031,14 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
}
@Override
public void refresh(String indexName, boolean waitForOperation) {
client.admin().indices().refresh(refreshRequest(indexName).force(waitForOperation)).actionGet();
public void refresh(String indexName) {
Assert.notNull(indexName, "No index defined for refresh()");
client.admin().indices().refresh(refreshRequest(indexName)).actionGet();
}
@Override
public <T> void refresh(Class<T> clazz, boolean waitForOperation) {
ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(clazz);
client.admin().indices()
.refresh(refreshRequest(persistentEntity.getIndexName()).force(waitForOperation)).actionGet();
public <T> void refresh(Class<T> clazz) {
refresh(getPersistentEntityFor(clazz).getIndexName());
}
@Override
@@ -1017,49 +1069,43 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
}
@Override
public Set<String> queryForAlias(String indexName) {
ClusterStateRequest clusterStateRequest = Requests.clusterStateRequest()
.routingTable(true).nodes(true).indices(indexName);
Iterator<String> iterator = client.admin().cluster().state(clusterStateRequest).actionGet().getState().getMetaData().aliases().keysIt();
return newHashSet(iterator);
public List<AliasMetaData> queryForAlias(String indexName) {
return client.admin().indices().getAliases(new GetAliasesRequest().indices(indexName))
.actionGet().getAliases().get(indexName);
}
private ElasticsearchPersistentEntity getPersistentEntityFor(Class clazz) {
@Override
public ElasticsearchPersistentEntity getPersistentEntityFor(Class clazz) {
Assert.isTrue(clazz.isAnnotationPresent(Document.class), "Unable to identify index name. " + clazz.getSimpleName()
+ " is not a Document. Make sure the document class is annotated with @Document(indexName=\"foo\")");
return elasticsearchConverter.getMappingContext().getPersistentEntity(clazz);
}
private String getPersistentEntityId(Object entity) {
PersistentProperty idProperty = getPersistentEntityFor(entity.getClass()).getIdProperty();
if (idProperty != null) {
Method getter = idProperty.getGetter();
if (getter != null) {
try {
Object id = getter.invoke(entity);
if (id != null) {
return String.valueOf(id);
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
return null;
ElasticsearchPersistentEntity<?> persistentEntity = getPersistentEntityFor(entity.getClass());
Object identifier = persistentEntity.getIdentifierAccessor(entity).getIdentifier();
return identifier == null ? null : String.valueOf(identifier);
}
private void setPersistentEntityId(Object entity, String id) {
PersistentProperty idProperty = getPersistentEntityFor(entity.getClass()).getIdProperty();
ElasticsearchPersistentEntity<?> persistentEntity = getPersistentEntityFor(entity.getClass());
PersistentProperty<?> idProperty = persistentEntity.getIdProperty();
// Only deal with String because ES generated Ids are strings !
if (idProperty != null && idProperty.getType().isAssignableFrom(String.class)) {
Method setter = idProperty.getSetter();
if (setter != null) {
try {
setter.invoke(entity, id);
} catch (Throwable t) {
t.printStackTrace();
}
}
persistentEntity.getPropertyAccessor(entity).setProperty(idProperty,id);
}
}
private void setPersistentEntityIndexAndType(Query query, Class clazz) {
if (query.getIndices().isEmpty()) {
query.addIndices(retrieveIndexNameFromPersistentEntity(clazz));
}
if (query.getTypes().isEmpty()) {
query.addTypes(retrieveTypeFromPersistentEntity(clazz));
}
}
@@ -1118,8 +1164,9 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
bufferedReader = new BufferedReader(inputStreamReader);
String line;
String lineSeparator = System.getProperty("line.separator");
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line);
stringBuilder.append(line).append(lineSeparator);
}
} catch (Exception e) {
logger.debug(String.format("Failed to load file from url: %s: %s", url, e.getMessage()));
@@ -1,70 +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.core;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.facet.FacetResult;
/**
* Container for query result and facet results
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
* @author Jonathan Yan
*/
public class FacetedPageImpl<T> extends PageImpl<T> implements FacetedPage<T> {
private List<FacetResult> facets;
private Map<String, FacetResult> mapOfFacets = new HashMap<String, FacetResult>();
public FacetedPageImpl(List<T> content) {
super(content);
}
public FacetedPageImpl(List<T> content, Pageable pageable, long total) {
super(content, pageable, total);
}
public FacetedPageImpl(List<T> content, Pageable pageable, long total, List<FacetResult> facets) {
super(content, pageable, total);
this.facets = facets;
for (FacetResult facet : facets) {
mapOfFacets.put(facet.getName(), facet);
}
}
@Override
public boolean hasFacets() {
return CollectionUtils.isNotEmpty(facets);
}
@Override
public List<FacetResult> getFacets() {
return facets;
}
@Override
public FacetResult getFacet(String name) {
return mapOfFacets.get(name);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* Copyright 2014-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,12 +25,14 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.springframework.core.GenericCollectionTypeResolver;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.annotation.Transient;
import org.springframework.data.elasticsearch.annotations.*;
import org.springframework.data.elasticsearch.core.completion.Completion;
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.util.ClassTypeInformation;
@@ -52,7 +54,7 @@ class MappingBuilder {
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 = "index_analyzer";
public static final String FIELD_INDEX_ANALYZER = "analyzer";
public static final String FIELD_PROPERTIES = "properties";
public static final String FIELD_PARENT = "_parent";
@@ -65,6 +67,8 @@ class MappingBuilder {
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();
@@ -108,11 +112,22 @@ class MappingBuilder {
continue;
}
boolean isGeoField = isGeoField(field);
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 (!isGeoField && !isCompletionField && isEntity(field) && isAnnotated(field)) {
if (!isGeoPointField && !isCompletionField && isEntity(field) && isAnnotated(field)) {
if (singleField == null) {
continue;
}
@@ -125,7 +140,7 @@ class MappingBuilder {
MultiField multiField = field.getAnnotation(MultiField.class);
if (isGeoField) {
if (isGeoPointField) {
applyGeoPointFieldMapping(xContentBuilder, field);
}
@@ -137,9 +152,9 @@ class MappingBuilder {
if (isRootObject && singleField != null && isIdField(field, idFieldName)) {
applyDefaultIdFieldMapping(xContentBuilder, field);
} else if (multiField != null) {
addMultiFieldMapping(xContentBuilder, field, multiField);
addMultiFieldMapping(xContentBuilder, field, multiField, isNestedOrObjectField(field));
} else if (singleField != null) {
addSingleFieldMapping(xContentBuilder, field, singleField);
addSingleFieldMapping(xContentBuilder, field, singleField, isNestedOrObjectField(field));
}
}
@@ -164,13 +179,31 @@ class MappingBuilder {
}
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;
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)
.endObject();
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 {
@@ -184,8 +217,8 @@ class MappingBuilder {
if (isNotBlank(annotation.searchAnalyzer())) {
xContentBuilder.field(FIELD_SEARCH_ANALYZER, annotation.searchAnalyzer());
}
if (isNotBlank(annotation.indexAnalyzer())) {
xContentBuilder.field(FIELD_INDEX_ANALYZER, annotation.indexAnalyzer());
if (isNotBlank(annotation.analyzer())) {
xContentBuilder.field(FIELD_INDEX_ANALYZER, annotation.analyzer());
}
}
xContentBuilder.endObject();
@@ -205,9 +238,11 @@ class MappingBuilder {
* @throws IOException
*/
private static void addSingleFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field,
Field fieldAnnotation) throws IOException {
Field fieldAnnotation, boolean nestedOrObjectField) throws IOException {
xContentBuilder.startObject(field.getName());
xContentBuilder.field(FIELD_STORE, fieldAnnotation.store());
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()) {
@@ -221,8 +256,8 @@ class MappingBuilder {
if (isNotBlank(fieldAnnotation.searchAnalyzer())) {
xContentBuilder.field(FIELD_SEARCH_ANALYZER, fieldAnnotation.searchAnalyzer());
}
if (isNotBlank(fieldAnnotation.indexAnalyzer())) {
xContentBuilder.field(FIELD_INDEX_ANALYZER, fieldAnnotation.indexAnalyzer());
if (isNotBlank(fieldAnnotation.analyzer())) {
xContentBuilder.field(FIELD_INDEX_ANALYZER, fieldAnnotation.analyzer());
}
xContentBuilder.endObject();
}
@@ -233,9 +268,9 @@ class MappingBuilder {
* @throws IOException
*/
private static void addNestedFieldMapping(XContentBuilder builder, java.lang.reflect.Field field,
NestedField annotation) throws IOException {
builder.startObject(field.getName() + "." + annotation.dotSuffix());
builder.field(FIELD_STORE, annotation.store());
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());
}
@@ -257,46 +292,19 @@ class MappingBuilder {
* @throws IOException
*/
private static void addMultiFieldMapping(XContentBuilder builder, java.lang.reflect.Field field,
MultiField annotation) throws IOException {
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());
for (NestedField nestedField : annotation.otherFields()) {
addNestedFieldMapping(builder, field, nestedField);
addSingleFieldMapping(builder, field, annotation.mainField(),nestedOrObjectField);
for (InnerField innerField : annotation.otherFields()) {
addNestedFieldMapping(builder, field, innerField);
}
builder.endObject();
builder.endObject();
}
/**
* Facet field for string type, for other types we don't need it(long, int, double, float)
*
* @throws IOException
*/
private static void addFacetMapping(XContentBuilder builder, java.lang.reflect.Field field, Field annotation) throws IOException {
builder.startObject(FacetRequest.FIELD_UNTOUCHED)
.field(FIELD_TYPE, TYPE_VALUE_STRING)
.field(FIELD_INDEX, INDEX_VALUE_NOT_ANALYZED)
.field(FIELD_STORE, true);
builder.endObject();
}
/**
* Sort field for string type, for other types we don't need it(long, int, double, float)
* value of the field should be converted to lowercase and not analise
*
* @throws IOException
*/
private static void addSortMapping(XContentBuilder builder, java.lang.reflect.Field field, Field annotation) throws IOException {
builder.startObject(FacetRequest.FIELD_SORT)
.field(FIELD_TYPE, TYPE_VALUE_STRING)
.field(FIELD_INDEX, "keyword")
.field(FIELD_STORE, true);
builder.endObject();
}
protected static boolean isEntity(java.lang.reflect.Field field) {
TypeInformation typeInformation = ClassTypeInformation.from(field.getType());
Class<?> clazz = getFieldType(field);
@@ -342,7 +350,7 @@ class MappingBuilder {
return fieldAnnotation != null && (FieldType.Nested == fieldAnnotation.type() || FieldType.Object == fieldAnnotation.type());
}
private static boolean isGeoField(java.lang.reflect.Field field) {
private static boolean isGeoPointField(java.lang.reflect.Field field) {
return field.getType() == GeoPoint.class || field.getAnnotation(GeoPointField.class) != null;
}
@@ -16,6 +16,7 @@
package org.springframework.data.elasticsearch.core;
import org.elasticsearch.action.search.SearchResponse;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
/**
@@ -23,5 +24,5 @@ import org.springframework.data.domain.Pageable;
*/
public interface SearchResultMapper {
<T> FacetedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable);
<T> Page<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable);
}
@@ -1,45 +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.core.facet;
import org.springframework.util.Assert;
/**
* @author Artur Konczak
*/
public abstract class AbstractFacetRequest implements FacetRequest {
private String name;
private boolean applyQueryFilter;
public AbstractFacetRequest(String name) {
Assert.hasText(name, "Facet can't be null or empty !!!");
this.name = name;
}
protected String getName() {
return name;
}
public void setApplyQueryFilter(boolean applyQueryFilter) {
this.applyQueryFilter = applyQueryFilter;
}
@Override
public boolean applyQueryFilter() {
return applyQueryFilter;
}
}
@@ -1,46 +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.core.facet;
import org.springframework.util.Assert;
/**
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
* @author Jonathan Yan
*/
public class AbstractFacetResult implements FacetResult {
private final String name;
private final FacetType type;
protected AbstractFacetResult(String name, FacetType type) {
Assert.hasText(name, "Facet name can't be null and should have a value");
this.name = name;
this.type = type;
}
@Override
public String getName() {
return name;
}
@Override
public FacetType getType() {
return type;
}
}
@@ -1,81 +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.core.facet;
import java.util.ArrayList;
import java.util.List;
import org.elasticsearch.search.facet.Facet;
import org.elasticsearch.search.facet.histogram.HistogramFacet;
import org.elasticsearch.search.facet.range.RangeFacet;
import org.elasticsearch.search.facet.statistical.StatisticalFacet;
import org.elasticsearch.search.facet.terms.TermsFacet;
import org.springframework.data.elasticsearch.core.facet.result.*;
/**
* @author Artur Konczak
* @author Petar Tahchiev
*/
public class DefaultFacetMapper {
public static FacetResult parse(Facet facet) {
if (facet instanceof TermsFacet) {
return parseTerm((TermsFacet) facet);
}
if (facet instanceof RangeFacet) {
return parseRange((RangeFacet) facet);
}
if (facet instanceof StatisticalFacet) {
return parseStatistical((StatisticalFacet) facet);
}
if (facet instanceof HistogramFacet) {
return parseHistogram((HistogramFacet) facet);
}
return null;
}
private static FacetResult parseTerm(TermsFacet facet) {
List<Term> entries = new ArrayList<Term>();
for (TermsFacet.Entry entry : facet.getEntries()) {
entries.add(new Term(entry.getTerm().toString(), entry.getCount()));
}
return new TermResult(facet.getName(), entries, facet.getTotalCount(), facet.getOtherCount(), facet.getMissingCount());
}
private static FacetResult parseRange(RangeFacet facet) {
List<Range> entries = new ArrayList<Range>();
for (RangeFacet.Entry entry : facet.getEntries()) {
entries.add(new Range(entry.getFrom() == Double.NEGATIVE_INFINITY ? null : entry.getFrom(), entry.getTo() == Double.POSITIVE_INFINITY ? null : entry.getTo(), entry.getCount(), entry.getTotal(), entry.getTotalCount(), entry.getMin(), entry.getMax()));
}
return new RangeResult(facet.getName(), entries);
}
private static FacetResult parseStatistical(StatisticalFacet facet) {
return new StatisticalResult(facet.getName(), facet.getCount(), facet.getMax(), facet.getMin(), facet.getMean(), facet.getStdDeviation(), facet.getSumOfSquares(), facet.getTotal(), facet.getVariance());
}
private static FacetResult parseHistogram(HistogramFacet facet) {
List<IntervalUnit> entries = new ArrayList<IntervalUnit>();
for (HistogramFacet.Entry entry : facet.getEntries()) {
entries.add(new IntervalUnit(entry.getKey(), entry.getCount(), entry.getTotalCount(), entry.getTotal(), entry.getMean(), entry.getMin(), entry.getMax()));
}
return new HistogramResult(facet.getName(), entries);
}
}
@@ -1,31 +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.core.facet;
/**
* Generic interface for all facets
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
* @author Jonathan Yan
*/
public interface FacetResult {
String getName();
FacetType getType();
}
@@ -1,69 +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.core.facet.request;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.search.facet.FacetBuilder;
import org.elasticsearch.search.facet.FacetBuilders;
import org.elasticsearch.search.facet.histogram.HistogramFacetBuilder;
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
import org.springframework.util.Assert;
/**
* @author Artur Konczak
* @author Mohsin Husen
*/
public class HistogramFacetRequest extends AbstractFacetRequest {
private String field;
private long interval;
private TimeUnit timeUnit;
public HistogramFacetRequest(String name) {
super(name);
}
public void setField(String field) {
this.field = field;
}
public void setInterval(long interval) {
this.interval = interval;
}
public void setTimeUnit(TimeUnit timeUnit) {
this.timeUnit = timeUnit;
}
public FacetBuilder getFacet() {
Assert.notNull(getName(), "Facet name can't be a null !!!");
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 !!!");
HistogramFacetBuilder builder = FacetBuilders.histogramFacet(getName());
builder.field(field);
if (timeUnit != null) {
builder.interval(interval, timeUnit);
} else {
builder.interval(interval);
}
return builder;
}
}
@@ -1,56 +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.core.facet.request;
import java.util.concurrent.TimeUnit;
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
/**
* @author Artur Konczak
*/
public class HistogramFacetRequestBuilder {
HistogramFacetRequest result;
public HistogramFacetRequestBuilder(String name) {
result = new HistogramFacetRequest(name);
}
public HistogramFacetRequestBuilder field(String field) {
result.setField(field);
return this;
}
public HistogramFacetRequestBuilder interval(long interval) {
result.setInterval(interval);
return this;
}
public HistogramFacetRequestBuilder timeUnit(TimeUnit timeUnit) {
result.setTimeUnit(timeUnit);
return this;
}
public FacetRequest build() {
return result;
}
public HistogramFacetRequestBuilder applyQueryFilter() {
result.setApplyQueryFilter(true);
return this;
}
}
@@ -1,48 +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.core.facet.request;
import org.elasticsearch.search.facet.FacetBuilder;
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
/**
* @author Artur Konczak
* @author Mohsin Husen
*/
public class NativeFacetRequest implements FacetRequest {
private FacetBuilder facet;
private boolean applyQueryFilter;
public NativeFacetRequest(FacetBuilder facet) {
this(facet, false);
}
public NativeFacetRequest(FacetBuilder facet, boolean applyQueryFilter) {
this.facet = facet;
this.applyQueryFilter = applyQueryFilter;
}
@Override
public FacetBuilder getFacet() {
return facet;
}
@Override
public boolean applyQueryFilter() {
return applyQueryFilter;
}
}
@@ -1,132 +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.core.facet.request;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.search.facet.FacetBuilder;
import org.elasticsearch.search.facet.FacetBuilders;
import org.elasticsearch.search.facet.range.RangeFacetBuilder;
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
import org.springframework.util.Assert;
/**
* Range facet for numeric fields
*
* @author Artur Konczak
* @author Akos Bordas
*/
public class RangeFacetRequest extends AbstractFacetRequest {
private String field;
private String keyField;
private String valueField;
private List<Entry> entries = new ArrayList<Entry>();
public RangeFacetRequest(String name) {
super(name);
}
public void setField(String field) {
this.field = field;
}
public void setFields(String keyField, String valueField) {
this.keyField = keyField;
this.valueField = valueField;
}
public void range(Double from, Double to) {
entries.add(new DoubleEntry(from, to));
}
public void range(String from, String to) {
entries.add(new StringEntry(from, to));
}
public void addRange(Double from, Double to) {
entries.add(new DoubleEntry(from, to));
}
public void addRange(String from, String to) {
entries.add(new StringEntry(from, to));
}
@Override
public FacetBuilder getFacet() {
Assert.notNull(getName(), "Facet name can't be a null !!!");
Assert.isTrue(StringUtils.isNotBlank(field) || StringUtils.isNotBlank(keyField) && StringUtils.isNotBlank(valueField), "Please select field or key field and value field !!!");
RangeFacetBuilder builder = FacetBuilders.rangeFacet(getName());
if (StringUtils.isNotBlank(keyField)) {
builder.keyField(keyField).valueField(valueField);
} else {
builder.field(field);
}
for (Entry entry : entries) {
if (entry instanceof DoubleEntry) {
DoubleEntry doubleEntry = (DoubleEntry) entry;
builder.addRange(validateValue(doubleEntry.getFrom(), Double.NEGATIVE_INFINITY), validateValue(doubleEntry.getTo(), Double.POSITIVE_INFINITY));
} else {
StringEntry stringEntry = (StringEntry) entry;
builder.addRange(stringEntry.getFrom(), stringEntry.getTo());
}
}
return builder;
}
private double validateValue(Double value, double defaultValue) {
return value == null ? defaultValue : value;
}
static class DoubleEntry extends Entry<Double> {
DoubleEntry(Double from, Double to) {
super(from, to);
}
}
static class StringEntry extends Entry<String> {
StringEntry(String from, String to) {
super(from, to);
}
}
static class Entry<T> {
T from;
T to;
Entry(T from, T to) {
this.from = from;
this.to = to;
}
public T getFrom() {
return from;
}
public T getTo() {
return to;
}
}
}
@@ -1,82 +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.core.facet.request;
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
/**
* Basic range facet
*
* @author Artur Konczak
*/
public class RangeFacetRequestBuilder {
RangeFacetRequest result;
public RangeFacetRequestBuilder(String name) {
result = new RangeFacetRequest(name);
}
public RangeFacetRequestBuilder field(String field) {
result.setField(field);
return this;
}
public RangeFacetRequestBuilder fields(String keyField, String valueField) {
result.setFields(keyField, valueField);
return this;
}
public RangeFacetRequestBuilder range(double from, double to) {
result.range(from, to);
return this;
}
public RangeFacetRequestBuilder range(String from, String to) {
result.range(from, to);
return this;
}
public RangeFacetRequestBuilder from(double from) {
result.range(from, null);
return this;
}
public RangeFacetRequestBuilder to(double to) {
result.range(null, to);
return this;
}
public RangeFacetRequestBuilder from(String from) {
result.range(from, null);
return this;
}
public RangeFacetRequestBuilder to(String to) {
result.range(null, to);
return this;
}
public RangeFacetRequestBuilder applyQueryFilter() {
result.setApplyQueryFilter(true);
return this;
}
public FacetRequest build() {
return result;
}
}
@@ -1,60 +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.core.facet.request;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.search.facet.FacetBuilder;
import org.elasticsearch.search.facet.FacetBuilders;
import org.elasticsearch.search.facet.statistical.StatisticalFacetBuilder;
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
import org.springframework.util.Assert;
/**
* @author Petar Tahchiev
*/
public class StatisticalFacetRequest extends AbstractFacetRequest {
private String field;
private String[] fields;
public StatisticalFacetRequest(String name) {
super(name);
}
public void setField(String field) {
this.field = field;
}
public void setFields(String... fields) {
this.fields = fields;
}
public FacetBuilder getFacet() {
Assert.notNull(getName(), "Facet name can't be a null !!!");
Assert.isTrue(StringUtils.isNotBlank(field) && fields == null, "Please select field or fields on which to build the facets !!!");
StatisticalFacetBuilder builder = FacetBuilders.statisticalFacet(getName());
if (ArrayUtils.isNotEmpty(fields)) {
builder.fields(fields);
} else {
builder.field(field);
}
return builder;
}
}
@@ -1,49 +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.core.facet.request;
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
/**
* @author Petar Tahchiev
*/
public class StatisticalFacetRequestBuilder {
StatisticalFacetRequest result;
public StatisticalFacetRequestBuilder(String name) {
result = new StatisticalFacetRequest(name);
}
public StatisticalFacetRequestBuilder field(String field) {
result.setField(field);
return this;
}
public StatisticalFacetRequestBuilder fields(String... fields) {
result.setFields(fields);
return this;
}
public StatisticalFacetRequestBuilder applyQueryFilter() {
result.setApplyQueryFilter(true);
return this;
}
public FacetRequest build() {
return result;
}
}
@@ -1,108 +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.core.facet.request;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.search.facet.FacetBuilder;
import org.elasticsearch.search.facet.FacetBuilders;
import org.elasticsearch.search.facet.terms.TermsFacet;
import org.elasticsearch.search.facet.terms.TermsFacetBuilder;
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
import org.springframework.util.Assert;
/**
* Term facet
*
* @author Artur Konczak
*/
public class TermFacetRequest extends AbstractFacetRequest {
private String[] fields;
private Object[] excludeTerms;
private int size = 10;
private TermFacetOrder order = TermFacetOrder.descCount;
private boolean allTerms = false;
private String regex = null;
private int regexFlag = 0;
public TermFacetRequest(String name) {
super(name);
}
public void setFields(String... fields) {
this.fields = fields;
}
public void setSize(int size) {
Assert.isTrue(size >= 0, "Size should be bigger then zero !!!");
this.size = size;
}
public void setOrder(TermFacetOrder order) {
this.order = order;
}
public void setExcludeTerms(Object... excludeTerms) {
this.excludeTerms = excludeTerms;
}
public void setAllTerms(boolean allTerms) {
this.allTerms = allTerms;
}
public void setRegex(String regex) {
this.regex = regex;
}
public void setRegex(String regex, int regexFlag) {
this.regex = regex;
this.regexFlag = regexFlag;
}
@Override
public FacetBuilder getFacet() {
Assert.notEmpty(fields, "Please select at last one field !!!");
TermsFacetBuilder builder = FacetBuilders.termsFacet(getName()).fields(fields).size(size);
switch (order) {
case descTerm:
builder.order(TermsFacet.ComparatorType.REVERSE_TERM);
break;
case ascTerm:
builder.order(TermsFacet.ComparatorType.TERM);
break;
case ascCount:
builder.order(TermsFacet.ComparatorType.REVERSE_COUNT);
break;
default:
builder.order(TermsFacet.ComparatorType.COUNT);
}
if (ArrayUtils.isNotEmpty(excludeTerms)) {
builder.exclude(excludeTerms);
}
if (allTerms) {
builder.allTerms(allTerms);
}
if (StringUtils.isNotBlank(regex)) {
builder.regex(regex, regexFlag);
}
return builder;
}
}
@@ -1,91 +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.core.facet.request;
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
/**
* Basic term facet
*
* @author Artur Konczak
*/
public class TermFacetRequestBuilder {
private TermFacetRequest result;
public TermFacetRequestBuilder(String name) {
result = new TermFacetRequest(name);
}
public TermFacetRequestBuilder fields(String... fields) {
result.setFields(fields);
return this;
}
public TermFacetRequestBuilder size(int size) {
result.setSize(size);
return this;
}
public TermFacetRequestBuilder excludeTerms(Object... terms) {
result.setExcludeTerms(terms);
return this;
}
public TermFacetRequestBuilder allTerms() {
result.setAllTerms(true);
return this;
}
public TermFacetRequestBuilder regex(String regex) {
result.setRegex(regex);
return this;
}
public TermFacetRequestBuilder regex(String regex, int regexFlag) {
result.setRegex(regex, regexFlag);
return this;
}
public TermFacetRequestBuilder ascTerm() {
result.setOrder(TermFacetOrder.ascTerm);
return this;
}
public TermFacetRequestBuilder descTerm() {
result.setOrder(TermFacetOrder.descTerm);
return this;
}
public TermFacetRequestBuilder ascCount() {
result.setOrder(TermFacetOrder.ascCount);
return this;
}
public TermFacetRequestBuilder descCount() {
result.setOrder(TermFacetOrder.descCount);
return this;
}
public TermFacetRequestBuilder applyQueryFilter() {
result.setApplyQueryFilter(true);
return this;
}
public FacetRequest build() {
return result;
}
}
@@ -1,38 +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.core.facet.result;
import java.util.List;
import org.springframework.data.elasticsearch.core.facet.AbstractFacetResult;
import org.springframework.data.elasticsearch.core.facet.FacetType;
/**
* @author Artur Konczak
*/
public class HistogramResult extends AbstractFacetResult {
private List<IntervalUnit> terms;
public HistogramResult(String name, List<IntervalUnit> terms) {
super(name, FacetType.term);
this.terms = terms;
}
public List<IntervalUnit> getIntervalUnit() {
return terms;
}
}
@@ -1,91 +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.core.facet.result;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Single term
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
* @author Jonathan Yan
*/
public class IntervalUnit {
private static final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
long key;
long count;
long totalCount;
double total;
double mean;
double min;
double max;
public IntervalUnit(long key, long count, long totalCount, double total, double mean, double min, double max) {
this.key = key;
this.count = count;
this.totalCount = totalCount;
this.total = total;
this.mean = mean;
this.min = min;
this.max = max;
}
public long getKey() {
return key;
}
public long getCount() {
return count;
}
public long getTotalCount() {
return totalCount;
}
public double getTotal() {
return total;
}
public double getMean() {
return mean;
}
public double getMin() {
return min;
}
public double getMax() {
return max;
}
@Override
public String toString() {
return "IntervalUnit{" +
"key=" + format.format(new Date(key)) +
", count=" + count +
", totalCount=" + totalCount +
", total=" + total +
", mean=" + mean +
", min=" + min +
", max=" + max +
'}';
}
}
@@ -1,78 +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.core.facet.result;
/**
* Single range
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
* @author Jonathan Yan
*/
public class Range {
private Double from;
private Double to;
private long count;
private double total;
private double totalCount;
private double min = Double.POSITIVE_INFINITY;
private double max = Double.NEGATIVE_INFINITY;
public Range(Double from, Double to, long count, double total, double totalCount, double min, double max) {
this.from = from;
this.to = to;
this.count = count;
this.total = total;
this.totalCount = totalCount;
this.min = min;
this.max = max;
}
public Double getFrom() {
return from;
}
public Double getTo() {
return to;
}
/**
* Return number of documents in range
*
* @return
*/
public long getCount() {
return count;
}
public double getTotal() {
return total;
}
public double getTotalCount() {
return totalCount;
}
public double getMin() {
return min;
}
public double getMax() {
return max;
}
}
@@ -1,43 +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.core.facet.result;
import java.util.List;
import org.springframework.data.elasticsearch.core.facet.AbstractFacetResult;
import org.springframework.data.elasticsearch.core.facet.FacetType;
/**
* Basic term facet result
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
* @author Jonathan Yan
*/
public class RangeResult extends AbstractFacetResult {
private List<Range> ranges;
public RangeResult(String name, List<Range> ranges) {
super(name, FacetType.range);
this.ranges = ranges;
}
public List<Range> getRanges() {
return ranges;
}
}
@@ -1,85 +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.core.facet.result;
import org.springframework.data.elasticsearch.core.facet.AbstractFacetResult;
import org.springframework.data.elasticsearch.core.facet.FacetType;
/**
* @author Petar Tahchiev
*/
public class StatisticalResult extends AbstractFacetResult {
private long count;
private double max;
private double min;
private double mean;
private double stdDeviation;
private double sumOfSquares;
private double total;
private double variance;
public StatisticalResult(String name, long count, double max, double min, double mean, double stdDeviation, double sumOfSquares, double total, double variance) {
super(name, FacetType.statistical);
this.count = count;
this.max = max;
this.min = min;
this.mean = mean;
this.stdDeviation = stdDeviation;
this.sumOfSquares = sumOfSquares;
this.total = total;
this.variance = variance;
}
public long getCount() {
return count;
}
public double getMax() {
return max;
}
public double getMin() {
return min;
}
public double getMean() {
return mean;
}
public double getStdDeviation() {
return stdDeviation;
}
public double getSumOfSquares() {
return sumOfSquares;
}
public double getTotal() {
return total;
}
public double getVariance() {
return variance;
}
}
@@ -1,62 +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.core.facet.result;
import java.util.List;
import org.springframework.data.elasticsearch.core.facet.AbstractFacetResult;
import org.springframework.data.elasticsearch.core.facet.FacetType;
/**
* Basic term facet result
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
* @author Jonathan Yan
* @author Matija Obreza
*/
public class TermResult extends AbstractFacetResult {
private List<Term> terms;
private long total;
private long other;
private long missing;
public TermResult(String name, List<Term> terms, long total, long other, long missing) {
super(name, FacetType.term);
this.terms = terms;
this.total = total;
this.other = other;
this.missing = missing;
}
public List<Term> getTerms() {
return terms;
}
public long getTotal() {
return total;
}
public long getOther() {
return other;
}
public long getMissing() {
return missing;
}
}
@@ -0,0 +1,70 @@
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;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.data.geo.Point;
/**
* @author Artur Konaczak
*/
public class CustomGeoModule extends SimpleModule {
private static final long serialVersionUID = 1L;
/**
* Creates a new {@link org.springframework.data.elasticsearch.core.geo.CustomGeoModule} registering serializers and deserializers for spring data commons geo-spatial types.
*/
public CustomGeoModule() {
super("Spring Data Elasticsearch Geo", new Version(1, 0, 0, null, "org.springframework.data.elasticsearch", "spring-data-elasticsearch-geo"));
addSerializer(Point.class, new PointSerializer());
addDeserializer(Point.class, new PointDeserializer());
}
}
class PointSerializer extends JsonSerializer<Point> {
@Override
public void serialize(Point value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
gen.writeObject(GeoPoint.fromPoint(value));
// gen.writeStartObject();
// gen.writeNumberField("lat", value.getY());
// gen.writeNumberField("lon", value.getX());
// gen.writeEndObject();
}
}
class PointDeserializer extends JsonDeserializer<Point> {
@Override
public Point deserialize(JsonParser p, DeserializationContext context) throws IOException, JsonProcessingException {
GeoPoint point = p.readValueAs(GeoPoint.class);
// Double lat = null;
// Double lon = null;
// //skipp field name
// p.nextFieldName();
// if ("lat".equals(p.getCurrentName())) {
// //get value
// p.nextFieldName();
// lat = p.getDoubleValue();
// p.nextFieldName();
// }
// if ("lon".equals(p.getCurrentName())) {
// //get value
// p.nextFieldName();
// lon = p.getDoubleValue();
// }
// return new Point(lon, lat);
return GeoPoint.toPoint(point);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@ import org.springframework.data.geo.Point;
* geo-location used for #{@link org.springframework.data.elasticsearch.core.query.Criteria}.
*
* @author Franck Marchand
* @author Mohsin Husen
*/
public class GeoPoint {
@@ -51,7 +52,11 @@ public class GeoPoint {
* @return a {@link org.springframework.data.elasticsearch.core.geo.GeoPoint}
*/
public static GeoPoint fromPoint(Point point) {
return new GeoPoint(point.getY(), point.getX());
return new GeoPoint(point.getX(), point.getY());
}
public static Point toPoint(GeoPoint point) {
return new Point(point.getLat(), point.getLon());
}
}
@@ -34,6 +34,8 @@ public interface ElasticsearchPersistentEntity<T> extends PersistentEntity<T, El
short getReplicas();
boolean isUseServerConfiguration();
String getRefreshInterval();
String getIndexStoreType();
@@ -45,4 +47,6 @@ public interface ElasticsearchPersistentEntity<T> extends PersistentEntity<T, El
ElasticsearchPersistentProperty getParentIdProperty();
String settingPath();
boolean isCreateIndexAndMapping();
}
@@ -50,6 +50,7 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
private String indexName;
private String indexType;
private boolean useServerConfiguration;
private short shards;
private short replicas;
private String refreshInterval;
@@ -57,6 +58,7 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
private String parentType;
private ElasticsearchPersistentProperty parentIdProperty;
private String settingPath;
private boolean createIndexAndMapping;
public SimpleElasticsearchPersistentEntity(TypeInformation<T> typeInformation) {
super(typeInformation);
@@ -68,12 +70,14 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
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 = typeInformation.getType().getAnnotation(Document.class).indexName();
this.indexName = document.indexName();
this.indexType = hasText(document.type()) ? document.type() : clazz.getSimpleName().toLowerCase(Locale.ENGLISH);
this.shards = typeInformation.getType().getAnnotation(Document.class).shards();
this.replicas = typeInformation.getType().getAnnotation(Document.class).replicas();
this.refreshInterval = typeInformation.getType().getAnnotation(Document.class).refreshInterval();
this.indexStoreType = typeInformation.getType().getAnnotation(Document.class).indexStoreType();
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();
@@ -114,6 +118,11 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
return replicas;
}
@Override
public boolean isUseServerConfiguration() {
return useServerConfiguration;
}
@Override
public String getRefreshInterval() {
return refreshInterval;
@@ -134,6 +143,11 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
return settingPath;
}
@Override
public boolean isCreateIndexAndMapping() {
return createIndexAndMapping;
}
@Override
public void addPersistentProperty(ElasticsearchPersistentProperty property) {
super.addPersistentProperty(property);
@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,12 +15,10 @@
*/
package org.springframework.data.elasticsearch.core.query;
import static org.apache.commons.collections.CollectionUtils.*;
import static java.util.Collections.addAll;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.elasticsearch.action.search.SearchType;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
@@ -39,6 +37,7 @@ abstract class AbstractQuery implements Query {
protected List<String> indices = new ArrayList<String>();
protected List<String> types = new ArrayList<String>();
protected List<String> fields = new ArrayList<String>();
protected SourceFilter sourceFilter;
protected float minScore;
protected Collection<String> ids;
protected String route;
@@ -91,6 +90,16 @@ abstract class AbstractQuery implements Query {
return types;
}
@Override
public void addSourceFilter(SourceFilter sourceFilter) {
this.sourceFilter = sourceFilter;
}
@Override
public SourceFilter getSourceFilter() {
return sourceFilter;
}
@SuppressWarnings("unchecked")
public final <T extends Query> T addSort(Sort sort) {
if (sort == null) {
@@ -17,7 +17,7 @@ package org.springframework.data.elasticsearch.core.query;
import java.util.Map;
import org.elasticsearch.index.query.FilterBuilder;
import org.elasticsearch.index.query.QueryBuilder;
/**
* @author Mohsin Husen
@@ -26,7 +26,7 @@ public class AliasBuilder {
private String indexName;
private String aliasName;
private FilterBuilder filterBuilder;
private QueryBuilder filterBuilder;
private Map<String, Object> filter;
private String searchRouting;
private String indexRouting;
@@ -42,7 +42,7 @@ public class AliasBuilder {
return this;
}
public AliasBuilder withFilterBuilder(FilterBuilder filterBuilder) {
public AliasBuilder withFilterBuilder(QueryBuilder filterBuilder) {
this.filterBuilder = filterBuilder;
return this;
}
@@ -17,7 +17,7 @@ package org.springframework.data.elasticsearch.core.query;
import java.util.Map;
import org.elasticsearch.index.query.FilterBuilder;
import org.elasticsearch.index.query.QueryBuilder;
/**
* AliasQuery is useful for creating new alias or deleting existing ones
@@ -28,7 +28,7 @@ public class AliasQuery {
private String indexName;
private String aliasName;
private FilterBuilder filterBuilder;
private QueryBuilder filterBuilder;
private Map<String, Object> filter;
private String searchRouting;
private String indexRouting;
@@ -50,11 +50,11 @@ public class AliasQuery {
this.aliasName = aliasName;
}
public FilterBuilder getFilterBuilder() {
public QueryBuilder getFilterBuilder() {
return filterBuilder;
}
public void setFilterBuilder(FilterBuilder filterBuilder) {
public void setFilterBuilder(QueryBuilder filterBuilder) {
this.filterBuilder = filterBuilder;
}
@@ -21,6 +21,7 @@ import org.apache.commons.lang.StringUtils;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.elasticsearch.core.geo.GeoBox;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.geo.Box;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Point;
import org.springframework.util.Assert;
@@ -35,6 +36,17 @@ import org.springframework.util.Assert;
*/
public class Criteria {
@Override
public String toString() {
return "Criteria{" +
"field=" + field.getName() +
", boost=" + boost +
", negating=" + negating +
", queryCriteria=" + StringUtils.join(queryCriteria, '|') +
", filterCriteria=" + StringUtils.join(filterCriteria, '|') +
'}';
}
public static final String WILDCARD = "*";
public static final String CRITERIA_VALUE_SEPERATOR = " ";
@@ -71,7 +83,6 @@ public class Criteria {
public Criteria(Field field) {
Assert.notNull(field, "Field for criteria must not be null");
Assert.hasText(field.getName(), "Field.name for criteria must not be null/empty");
this.criteriaChain.add(this);
this.field = field;
}
@@ -304,7 +315,18 @@ public class Criteria {
* @return
*/
public Criteria lessThanEqual(Object upperBound) {
between(null, upperBound);
if (upperBound == null) {
throw new InvalidDataAccessApiUsageException("UpperBound can't be null");
}
queryCriteria.add(new CriteriaEntry(OperationKey.LESS_EQUAL, upperBound));
return this;
}
public Criteria lessThan(Object upperBound) {
if (upperBound == null) {
throw new InvalidDataAccessApiUsageException("UpperBound can't be null");
}
queryCriteria.add(new CriteriaEntry(OperationKey.LESS, upperBound));
return this;
}
@@ -315,7 +337,18 @@ public class Criteria {
* @return
*/
public Criteria greaterThanEqual(Object lowerBound) {
between(lowerBound, null);
if (lowerBound == null) {
throw new InvalidDataAccessApiUsageException("LowerBound can't be null");
}
queryCriteria.add(new CriteriaEntry(OperationKey.GREATER_EQUAL, lowerBound));
return this;
}
public Criteria greaterThan(Object lowerBound) {
if (lowerBound == null) {
throw new InvalidDataAccessApiUsageException("LowerBound can't be null");
}
queryCriteria.add(new CriteriaEntry(OperationKey.GREATER, lowerBound));
return this;
}
@@ -326,12 +359,7 @@ public class Criteria {
* @return
*/
public Criteria in(Object... values) {
if (values.length == 0 || (values.length > 1 && values[1] instanceof Collection)) {
throw new InvalidDataAccessApiUsageException("At least one element "
+ (values.length > 0 ? ("of argument of type " + values[1].getClass().getName()) : "")
+ " has to be present.");
}
return in(Arrays.asList(values));
return in(toCollection(values));
}
/**
@@ -346,6 +374,25 @@ public class Criteria {
return this;
}
private List<Object> toCollection(Object... values) {
if (values.length == 0 || (values.length > 1 && values[1] instanceof Collection)) {
throw new InvalidDataAccessApiUsageException("At least one element "
+ (values.length > 0 ? ("of argument of type " + values[1].getClass().getName()) : "")
+ " has to be present.");
}
return Arrays.asList(values);
}
public Criteria notIn(Object... values) {
return notIn(toCollection(values));
}
public Criteria notIn(Iterable<?> values) {
Assert.notNull(values, "Collection of 'NotIn' values must not be null");
queryCriteria.add(new CriteriaEntry(OperationKey.NOT_IN, values));
return this;
}
/**
* Creates new CriteriaEntry for {@code location WITHIN distance}
*
@@ -407,6 +454,17 @@ public class Criteria {
return this;
}
/**
* Creates new CriteriaEntry for {@code location Box bounding box}
*
* @param boundingBox {@link org.springframework.data.elasticsearch.core.geo.GeoBox} bounding box(left top corner + right bottom corner)
* @return Criteria the chaind criteria with the new 'boundingBox' criteria included.
*/
public Criteria boundedBy(Box boundingBox) {
Assert.notNull(boundingBox, "boundingBox value for boundedBy criteria must not be null");
filterCriteria.add(new CriteriaEntry(OperationKey.BBOX, new Object[]{boundingBox.getFirst(), boundingBox.getSecond()}));
return this;
}
/**
* Creates new CriteriaEntry for bounding box created from points
@@ -436,10 +494,17 @@ public class Criteria {
return this;
}
public Criteria boundedBy(Point topLeftPoint, Point bottomRightPoint) {
Assert.notNull(topLeftPoint, "topLeftPoint must not be null");
Assert.notNull(bottomRightPoint, "bottomRightPoint must not be null");
filterCriteria.add(new CriteriaEntry(OperationKey.BBOX, new Object[]{GeoPoint.fromPoint(topLeftPoint), GeoPoint.fromPoint(bottomRightPoint)}));
return this;
}
private void assertNoBlankInWildcardedQuery(String searchString, boolean leadingWildcard, boolean trailingWildcard) {
if (StringUtils.contains(searchString, CRITERIA_VALUE_SEPERATOR)) {
throw new InvalidDataAccessApiUsageException("Cannot constructQuery '" + (leadingWildcard ? "*" : "") + "\""
+ searchString + "\"" + (trailingWildcard ? "*" : "") + "'. Use epxression or mulitple clauses instead.");
+ searchString + "\"" + (trailingWildcard ? "*" : "") + "'. Use expression or multiple clauses instead.");
}
}
@@ -522,7 +587,7 @@ public class Criteria {
}
public enum OperationKey {
EQUALS, CONTAINS, STARTS_WITH, ENDS_WITH, EXPRESSION, BETWEEN, FUZZY, IN, WITHIN, BBOX, NEAR;
EQUALS, CONTAINS, STARTS_WITH, ENDS_WITH, EXPRESSION, BETWEEN, FUZZY, IN, NOT_IN, WITHIN, BBOX, NEAR, LESS, LESS_EQUAL, GREATER, GREATER_EQUAL;
}
public static class CriteriaEntry {
@@ -542,5 +607,13 @@ public class Criteria {
public Object getValue() {
return value;
}
@Override
public String toString() {
return "CriteriaEntry{" +
"key=" + key +
", value=" + value +
'}';
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,6 +28,8 @@ public class DeleteQuery {
private QueryBuilder query;
private String index;
private String type;
private Integer pageSize;
private Long scrollTimeInMillis;
public QueryBuilder getQuery() {
return query;
@@ -52,4 +54,20 @@ public class DeleteQuery {
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;
}
}
@@ -0,0 +1,42 @@
/*
* Copyright 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;
/**
* SourceFilter implementation for providing includes and excludes.
*
* @Author Jon Tsiros
*/
public class FetchSourceFilter implements SourceFilter {
private final String[] includes;
private final String[] excludes;
public FetchSourceFilter(final String[] includes, final String[] excludes) {
this.includes = includes;
this.excludes = excludes;
}
@Override
public String[] getIncludes() {
return includes;
}
@Override
public String[] getExcludes() {
return excludes;
}
}
@@ -0,0 +1,45 @@
/*
* Copyright 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;
/**
* SourceFilter builder for providing includes and excludes.
*
* @Author Jon Tsiros
*/
public class FetchSourceFilterBuilder {
private String[] includes;
private String[] excludes;
public FetchSourceFilterBuilder withIncludes(String... includes) {
this.includes = includes;
return this;
}
public FetchSourceFilterBuilder withExcludes(String... excludes) {
this.excludes = excludes;
return this;
}
public SourceFilter build() {
if (includes == null) includes = new String[0];
if (excludes == null) excludes = new String[0];
SourceFilter sourceFilter = new FetchSourceFilter(includes, excludes);
return sourceFilter;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* Copyright 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.
@@ -13,24 +13,30 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.elasticsearch.core;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.elasticsearch.core.facet.FacetResult;
package org.springframework.data.elasticsearch.core.query;
/**
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
* @author Jonathan Yan
* Defines a IndexBoost to be applied on the "indices_boost" query clause
*
* @author Thiago Locatelli
*/
public interface FacetedPage<T> extends Page<T> {
public class IndexBoost {
boolean hasFacets();
private String indexName;
private float boost;
List<FacetResult> getFacets();
public IndexBoost(String indexName, float boost) {
this.indexName = indexName;
this.boost = boost;
}
public String getIndexName() {
return indexName;
}
public float getBoost() {
return boost;
}
FacetResult getFacet(String name);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
*/
package org.springframework.data.elasticsearch.core.query;
import static org.apache.commons.collections.CollectionUtils.*;
import static java.util.Collections.addAll;
import static org.springframework.data.elasticsearch.core.query.AbstractQuery.*;
import java.util.ArrayList;
@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,15 +15,15 @@
*/
package org.springframework.data.elasticsearch.core.query;
import org.elasticsearch.index.query.FilterBuilder;
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.ArrayList;
import java.util.List;
import java.util.Arrays;
/**
* NativeSearchQuery
@@ -35,29 +35,31 @@ import java.util.List;
public class NativeSearchQuery extends AbstractQuery implements SearchQuery {
private QueryBuilder query;
private FilterBuilder filter;
private QueryBuilder filter;
private List<SortBuilder> sorts;
private List<FacetRequest> facets;
private final List<ScriptField> scriptFields = new ArrayList<ScriptField>();
/*private List<FacetRequest> facets;*/
private List<AbstractAggregationBuilder> aggregations;
private HighlightBuilder.Field[] highlightFields;
private List<IndexBoost> indicesBoost;
public NativeSearchQuery(QueryBuilder query) {
this.query = query;
}
public NativeSearchQuery(QueryBuilder query, FilterBuilder filter) {
public NativeSearchQuery(QueryBuilder query, QueryBuilder filter) {
this.query = query;
this.filter = filter;
}
public NativeSearchQuery(QueryBuilder query, FilterBuilder filter, List<SortBuilder> sorts) {
public NativeSearchQuery(QueryBuilder query, QueryBuilder filter, List<SortBuilder> sorts) {
this.query = query;
this.filter = filter;
this.sorts = sorts;
}
public NativeSearchQuery(QueryBuilder query, FilterBuilder filter, List<SortBuilder> sorts, HighlightBuilder.Field[] highlightFields) {
public NativeSearchQuery(QueryBuilder query, QueryBuilder filter, List<SortBuilder> sorts, HighlightBuilder.Field[] highlightFields) {
this.query = query;
this.filter = filter;
this.sorts = sorts;
@@ -68,7 +70,7 @@ public class NativeSearchQuery extends AbstractQuery implements SearchQuery {
return query;
}
public FilterBuilder getFilter() {
public QueryBuilder getFilter() {
return filter;
}
@@ -81,7 +83,18 @@ public class NativeSearchQuery extends AbstractQuery implements SearchQuery {
return highlightFields;
}
public void addFacet(FacetRequest facetRequest) {
@Override
public List<ScriptField> getScriptFields() { return scriptFields; }
public void setScriptFields(List<ScriptField> scriptFields) {
this.scriptFields.addAll(scriptFields);
}
public void addScriptField(ScriptField... scriptField) {
scriptFields.addAll(Arrays.asList(scriptField));
}
/* public void addFacet(FacetRequest facetRequest) {
if (facets == null) {
facets = new ArrayList<FacetRequest>();
}
@@ -95,7 +108,7 @@ public class NativeSearchQuery extends AbstractQuery implements SearchQuery {
@Override
public List<FacetRequest> getFacets() {
return facets;
}
}*/
@Override
public List<AbstractAggregationBuilder> getAggregations() {
@@ -113,4 +126,14 @@ public class NativeSearchQuery extends AbstractQuery implements SearchQuery {
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,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors.
* Copyright 2013-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,19 +15,16 @@
*/
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.apache.commons.collections.CollectionUtils;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.index.query.FilterBuilder;
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
@@ -40,15 +37,17 @@ import org.springframework.data.elasticsearch.core.facet.FacetRequest;
public class NativeSearchQueryBuilder {
private QueryBuilder queryBuilder;
private FilterBuilder filterBuilder;
private QueryBuilder filterBuilder;
private List<ScriptField> scriptFields = new ArrayList<ScriptField>();
private List<SortBuilder> sortBuilders = new ArrayList<SortBuilder>();
private List<FacetRequest> facetRequests = new ArrayList<FacetRequest>();
private List<AbstractAggregationBuilder> aggregationBuilders = new ArrayList<AbstractAggregationBuilder>();
private HighlightBuilder.Field[] highlightFields;
private Pageable pageable;
private String[] indices;
private String[] types;
private String[] fields;
private SourceFilter sourceFilter;
private List<IndexBoost> indicesBoost;
private float minScore;
private Collection<String> ids;
private String route;
@@ -59,7 +58,7 @@ public class NativeSearchQueryBuilder {
return this;
}
public NativeSearchQueryBuilder withFilter(FilterBuilder filterBuilder) {
public NativeSearchQueryBuilder withFilter(QueryBuilder filterBuilder) {
this.filterBuilder = filterBuilder;
return this;
}
@@ -69,21 +68,31 @@ public class NativeSearchQueryBuilder {
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) {
/* 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;
@@ -104,6 +113,11 @@ public class NativeSearchQueryBuilder {
return this;
}
public NativeSearchQueryBuilder withSourceFilter(SourceFilter sourceFilter) {
this.sourceFilter = sourceFilter;
return this;
}
public NativeSearchQueryBuilder withMinScore(float minScore) {
this.minScore = minScore;
return this;
@@ -142,11 +156,19 @@ public class NativeSearchQueryBuilder {
nativeSearchQuery.addFields(fields);
}
if (CollectionUtils.isNotEmpty(facetRequests)) {
nativeSearchQuery.setFacets(facetRequests);
if (sourceFilter != null) {
nativeSearchQuery.addSourceFilter(sourceFilter);
}
if(indicesBoost != null) {
nativeSearchQuery.setIndicesBoost(indicesBoost);
}
if (!isEmpty(scriptFields)) {
nativeSearchQuery.setScriptFields(scriptFields);
}
if (CollectionUtils.isNotEmpty(aggregationBuilders)) {
if (!isEmpty(aggregationBuilders)) {
nativeSearchQuery.setAggregations(aggregationBuilders);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -111,6 +111,21 @@ public interface Query {
*/
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
*
@@ -0,0 +1,26 @@
package org.springframework.data.elasticsearch.core.query;
import org.elasticsearch.script.Script;
/**
* @author Ryan Murfitt
* @author Artur Konczak
*/
public class ScriptField {
private final String fieldName;
private final Script script;
public ScriptField(String fieldName, Script script) {
this.fieldName = fieldName;
this.script = script;
}
public String fieldName() {
return fieldName;
}
public Script script() {
return script;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,12 +17,10 @@ package org.springframework.data.elasticsearch.core.query;
import java.util.List;
import org.elasticsearch.index.query.FilterBuilder;
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
@@ -35,13 +33,18 @@ public interface SearchQuery extends Query {
QueryBuilder getQuery();
FilterBuilder getFilter();
QueryBuilder getFilter();
List<SortBuilder> getElasticsearchSorts();
List<FacetRequest> getFacets();
/*List<FacetRequest> getFacets();*/
List<AbstractAggregationBuilder> getAggregations();
HighlightBuilder.Field[] getHighlightFields();
List<IndexBoost> getIndicesBoost();
List<ScriptField> getScriptFields();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* Copyright 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.
@@ -13,14 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.elasticsearch.core.facet;
package org.springframework.data.elasticsearch.core.query;
/**
* @author Artur Konczak
* @author Petar Tahchiev
* SourceFilter for providing includes and excludes.
*
* @Author Jon Tsiros
*/
public enum FacetType {
public interface SourceFilter {
term, range, histogram, statistical
String[] getIncludes();
String[] getExcludes();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,7 +20,6 @@ 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.FacetedPage;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.data.repository.NoRepositoryBean;
@@ -37,9 +36,11 @@ public interface ElasticsearchRepository<T, ID extends Serializable> extends Ela
Iterable<T> search(QueryBuilder query);
FacetedPage<T> search(QueryBuilder query, Pageable pageable);
Page<T> search(QueryBuilder query, Pageable pageable);
FacetedPage<T> search(SearchQuery searchQuery);
Page<T> search(SearchQuery searchQuery);
Page<T> searchSimilar(T entity, String[] fields, Pageable pageable);
void refresh();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors.
* Copyright 2013-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,7 +33,7 @@ import org.springframework.data.repository.cdi.CdiRepositoryBean;
import org.springframework.data.repository.cdi.CdiRepositoryExtensionSupport;
/**
* ElasticsearchRepositoryExtension
* CDI extension to export Elasticsearch repositories.
*
* @author Rizwan Idrees
* @author Mohsin Husen
@@ -42,14 +42,14 @@ import org.springframework.data.repository.cdi.CdiRepositoryExtensionSupport;
*/
public class ElasticsearchRepositoryExtension extends CdiRepositoryExtensionSupport {
private final Map<String, Bean<ElasticsearchOperations>> elasticsearchOperationsMap = new HashMap<String, Bean<ElasticsearchOperations>>();
private final Map<Set<Annotation>, Bean<ElasticsearchOperations>> elasticsearchOperationsMap = new HashMap<Set<Annotation>, Bean<ElasticsearchOperations>>();
@SuppressWarnings("unchecked")
<T> void processBean(@Observes ProcessBean<T> processBean) {
Bean<T> bean = processBean.getBean();
for (Type type : bean.getTypes()) {
if (type instanceof Class<?> && ElasticsearchOperations.class.isAssignableFrom((Class<?>) type)) {
elasticsearchOperationsMap.put(bean.getQualifiers().toString(), ((Bean<ElasticsearchOperations>) bean));
elasticsearchOperationsMap.put(bean.getQualifiers(), ((Bean<ElasticsearchOperations>) bean));
}
}
}
@@ -69,8 +69,7 @@ public class ElasticsearchRepositoryExtension extends CdiRepositoryExtensionSupp
private <T> CdiRepositoryBean<T> createRepositoryBean(Class<T> repositoryType, Set<Annotation> qualifiers,
BeanManager beanManager) {
Bean<ElasticsearchOperations> elasticsearchOperationsBean = this.elasticsearchOperationsMap.get(qualifiers
.toString());
Bean<ElasticsearchOperations> elasticsearchOperationsBean = this.elasticsearchOperationsMap.get(qualifiers);
if (elasticsearchOperationsBean == null) {
throw new UnsatisfiedResolutionException(String.format("Unable to resolve a bean for '%s' with qualifiers %s.",
@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ import java.lang.reflect.Method;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.elasticsearch.annotations.Query;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.query.QueryMethod;
import org.springframework.util.StringUtils;
@@ -28,26 +29,23 @@ import org.springframework.util.StringUtils;
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Oliver Gierke
*/
public class ElasticsearchQueryMethod extends QueryMethod {
private Method method;
private final Query queryAnnotation;
public ElasticsearchQueryMethod(Method method, RepositoryMetadata metadata) {
super(method, metadata);
this.method = method;
public ElasticsearchQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory) {
super(method, metadata, factory);
this.queryAnnotation = method.getAnnotation(Query.class);
}
public boolean hasAnnotatedQuery() {
return getQueryAnnotation() != null;
return this.queryAnnotation != null;
}
public String getAnnotatedQuery() {
String query = (String) AnnotationUtils.getValue(getQueryAnnotation(), "value");
String query = (String) AnnotationUtils.getValue(queryAnnotation, "value");
return StringUtils.hasText(query) ? query : null;
}
private Query getQueryAnnotation() {
return this.method.getAnnotation(Query.class);
}
}
@@ -41,6 +41,7 @@ import org.springframework.data.repository.query.parser.PartTree;
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Franck Marchand
* @author Artur Konczak
*/
public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuery, CriteriaQuery> {
@@ -112,12 +113,14 @@ public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuer
return criteria.endsWith(parameters.next().toString());
case CONTAINING:
return criteria.contains(parameters.next().toString());
case AFTER:
case GREATER_THAN:
return criteria.greaterThan(parameters.next());
case AFTER:
case GREATER_THAN_EQUAL:
return criteria.greaterThanEqual(parameters.next());
case BEFORE:
case LESS_THAN:
return criteria.lessThan(parameters.next());
case BEFORE:
case LESS_THAN_EQUAL:
return criteria.lessThanEqual(parameters.next());
case BETWEEN:
@@ -125,7 +128,7 @@ public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuer
case IN:
return criteria.in(asArray(parameters.next()));
case NOT_IN:
return criteria.in(asArray(parameters.next())).not();
return criteria.notIn(asArray(parameters.next()));
case SIMPLE_PROPERTY:
case WITHIN: {
Object firstParameter = parameters.next();
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors.
* Copyright 2013-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,13 +15,12 @@
*/
package org.springframework.data.elasticsearch.repository.support;
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
import static org.elasticsearch.index.query.QueryBuilders.*;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -30,19 +29,9 @@ import org.elasticsearch.index.query.QueryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.*;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.FacetedPage;
import org.springframework.data.elasticsearch.core.query.DeleteQuery;
import org.springframework.data.elasticsearch.core.query.GetQuery;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.MoreLikeThisQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.util.Assert;
@@ -78,8 +67,10 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
this.entityInformation = metadata;
setEntityClass(this.entityInformation.getJavaType());
try {
createIndex();
putMapping();
if (createIndexAndMapping()) {
createIndex();
putMapping();
}
} catch (ElasticsearchException exception) {
LOGGER.error("failed to load elasticsearch nodes : " + exception.getDetailedMessage());
}
@@ -93,6 +84,10 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
elasticsearchOperations.putMapping(getEntityClass());
}
private boolean createIndexAndMapping() {
return elasticsearchOperations.getPersistentEntityFor(getEntityClass()).isCreateIndexAndMapping();
}
@Override
public T findOne(ID id) {
GetQuery query = new GetQuery();
@@ -145,7 +140,7 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
public <S extends T> S save(S entity) {
Assert.notNull(entity, "Cannot save 'null' entity.");
elasticsearchOperations.index(createIndexQuery(entity));
elasticsearchOperations.refresh(entityInformation.getIndexName(), true);
elasticsearchOperations.refresh(entityInformation.getIndexName());
return entity;
}
@@ -157,7 +152,7 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
queries.add(createIndexQuery(s));
}
elasticsearchOperations.bulkIndex(queries);
elasticsearchOperations.refresh(entityInformation.getIndexName(), true);
elasticsearchOperations.refresh(entityInformation.getIndexName());
return entities;
}
@@ -169,15 +164,12 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
@Override
public <S extends T> Iterable<S> save(Iterable<S> entities) {
Assert.notNull(entities, "Cannot insert 'null' as a List.");
if (!(entities instanceof Collection<?>)) {
throw new InvalidDataAccessApiUsageException("Entities have to be inside a collection");
}
List<IndexQuery> queries = new ArrayList<IndexQuery>();
for (S s : entities) {
queries.add(createIndexQuery(s));
}
elasticsearchOperations.bulkIndex(queries);
elasticsearchOperations.refresh(entityInformation.getIndexName(), true);
elasticsearchOperations.refresh(entityInformation.getIndexName());
return entities;
}
@@ -198,13 +190,13 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
}
@Override
public FacetedPage<T> search(QueryBuilder query, Pageable pageable) {
public Page<T> search(QueryBuilder query, Pageable pageable) {
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(query).withPageable(pageable).build();
return elasticsearchOperations.queryForPage(searchQuery, getEntityClass());
}
@Override
public FacetedPage<T> search(SearchQuery query) {
public Page<T> search(SearchQuery query) {
return elasticsearchOperations.queryForPage(query, getEntityClass());
}
@@ -226,14 +218,14 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
Assert.notNull(id, "Cannot delete entity with id 'null'.");
elasticsearchOperations.delete(entityInformation.getIndexName(), entityInformation.getType(),
stringIdRepresentation(id));
elasticsearchOperations.refresh(entityInformation.getIndexName(), true);
elasticsearchOperations.refresh(entityInformation.getIndexName());
}
@Override
public void delete(T entity) {
Assert.notNull(entity, "Cannot delete 'null' entity.");
delete(extractIdFromBean(entity));
elasticsearchOperations.refresh(entityInformation.getIndexName(), true);
elasticsearchOperations.refresh(entityInformation.getIndexName());
}
@Override
@@ -249,7 +241,12 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
DeleteQuery deleteQuery = new DeleteQuery();
deleteQuery.setQuery(matchAllQuery());
elasticsearchOperations.delete(deleteQuery, getEntityClass());
elasticsearchOperations.refresh(entityInformation.getIndexName(), true);
elasticsearchOperations.refresh(entityInformation.getIndexName());
}
@Override
public void refresh() {
elasticsearchOperations.refresh(getEntityClass());
}
private IndexQuery createIndexQuery(T entity) {
@@ -311,14 +308,14 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
return null;
}
private List<String> stringIdsRepresentation(Iterable<ID> ids) {
Assert.notNull(ids, "ids can't be null.");
List<String> stringIds = new ArrayList<String>();
for (ID id : ids) {
stringIds.add(stringIdRepresentation(id));
}
return stringIds;
}
private List<String> stringIdsRepresentation(Iterable<ID> ids) {
Assert.notNull(ids, "ids can't be null.");
List<String> stringIds = new ArrayList<String>();
for (ID id : ids) {
stringIds.add(stringIdRepresentation(id));
}
return stringIds;
}
protected abstract String stringIdRepresentation(ID id);
@@ -25,6 +25,7 @@ import org.springframework.data.elasticsearch.repository.ElasticsearchRepository
import org.springframework.data.elasticsearch.repository.query.ElasticsearchPartQuery;
import org.springframework.data.elasticsearch.repository.query.ElasticsearchQueryMethod;
import org.springframework.data.elasticsearch.repository.query.ElasticsearchStringQuery;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
import org.springframework.data.repository.core.NamedQueries;
import org.springframework.data.repository.core.RepositoryInformation;
@@ -90,11 +91,16 @@ public class ElasticsearchRepositoryFactory extends RepositoryFactorySupport {
}
private class ElasticsearchQueryLookupStrategy implements QueryLookupStrategy {
/*
* (non-Javadoc)
* @see org.springframework.data.repository.query.QueryLookupStrategy#resolveQuery(java.lang.reflect.Method, org.springframework.data.repository.core.RepositoryMetadata, org.springframework.data.projection.ProjectionFactory, org.springframework.data.repository.core.NamedQueries)
*/
@Override
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, NamedQueries namedQueries) {
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory,
NamedQueries namedQueries) {
ElasticsearchQueryMethod queryMethod = new ElasticsearchQueryMethod(method, metadata);
ElasticsearchQueryMethod queryMethod = new ElasticsearchQueryMethod(method, metadata, factory);
String namedQueryName = queryMethod.getNamedQueryName();
if (namedQueries.hasQuery(namedQueryName)) {
@@ -42,6 +42,7 @@ public class ElasticsearchRepositoryFactoryBean<T extends Repository<S, ID>, S,
*/
public void setElasticsearchOperations(ElasticsearchOperations operations) {
Assert.notNull(operations);
setMappingContext(operations.getElasticsearchConverter().getMappingContext());
this.operations = operations;
}
+117
View File
@@ -1,6 +1,123 @@
Spring Data Elasticsearch Changelog
===================================
Changes in version 2.0.6.RELEASE (2016-12-21)
---------------------------------------------
* DATAES-304 - Release 2.0.6 (Hopper SR6).
Changes in version 2.1.0.RC1 (2016-12-21)
-----------------------------------------
* DATAES-315 - Adapt API in RepositoryFactoryBeanSupport implementation.
* DATAES-313 - Register repository factory in spring.factories for multi-store support.
* DATAES-289 - Upgrade to Elasticsearch 2.4.
* DATAES-284 - Downgrade to Jackson 2.7.5 until Elasticsearch is compatible with 2.8.
* DATAES-281 - Can't save entity without id setter.
* DATAES-275 - Release 2.1 RC1 (Ingalls).
Changes in version 3.0.0.M1 (2016-11-23)
----------------------------------------
* DATAES-307 - Set up 3.0 development.
* DATAES-306 - Release 3.0 M1 (Kay).
Changes in version 2.0.5.RELEASE (2016-11-03)
---------------------------------------------
* DATAES-300 - Release 2.0.5 (Hopper SR5).
Changes in version 2.0.4.RELEASE (2016-09-29)
---------------------------------------------
* DATAES-297 - Release 2.0.4 (Hopper SR4).
Changes in version 1.3.6.RELEASE (2016-09-29)
---------------------------------------------
* DATAES-299 - Release 1.3.6 (Gosling SR6).
Changes in version 1.3.5.RELEASE (2016-09-20)
---------------------------------------------
* DATAES-296 - Release 1.3.5 (Gosling SR5).
Changes in version 2.0.3.RELEASE (2016-09-20)
---------------------------------------------
* DATAES-281 - Can't save entity without id setter.
* DATAES-268 - Release 2.0.3 (Hopper SR3).
Changes in version 2.1.0.M1 (2016-07-27)
----------------------------------------
* DATAES-262 - Upgrade Elasticsearch to 2.3.3.
* DATAES-250 - Release 2.1 M1 (Ingalls).
Changes in version 2.0.2.RELEASE (2016-06-15)
---------------------------------------------
* DATAES-251 - Release 2.0.2 (Hopper SR2).
Changes in version 2.0.1.RELEASE (2016-04-06)
---------------------------------------------
* DATAES-249 - Release 2.0.1 (Hopper SR1).
Changes in version 2.0.0.RELEASE (2016-04-06)
---------------------------------------------
* DATAES-245 - Release 2.0 GA (Hopper).
Changes in version 2.0.0.RC1 (2016-03-18)
-----------------------------------------
* DATAES-241 - remove commons-collections dependency and use CollectionUtils from Spring Utils.
* DATAES-240 - Release 2.0 RC1 (Hopper).
* DATAES-238 - ElasticsearchTemplate.prepareUpdate() does not preserve routing parameter which is required for updating child documents.
* DATAES-237 - path-configuration fails to load configs from inside jars.
* DATAES-236 - Clear the search contexts associated with specified scroll id.
* DATAES-234 - CDI support can fail due to Set.toString() used as Map key.
* DATAES-211 - Upgrade to Elasticsearch 2.0.
* DATAES-188 - Source filtering feature Implementation.
* DATAES-124 - ElasticSearchTemplate should expose client.
Changes in version 1.4.0.M1 (2016-02-12)
----------------------------------------
* DATAES-232 - Add code of conduct.
* DATAES-231 - Release 1.4 M1 (Hopper).
* DATAES-230 - Remove unnecessary type check in AbstractElasticsearchRepository.
* DATAES-224 - ElasticsearchTemplate discards newlines in mappings and settings files.
* DATAES-221 - Adapt to changes in Spring Data Commons.
* DATAES-216 - Add support to Indices Boost.
* DATAES-210 - Typo in error message.
* DATAES-209 - Handle dynamic mapping annotation at field level.
* DATAES-194 - Tests should clean up "data" directory.
* DATAES-171 - findByIdNotIn not work.
* DATAES-94 - Bump to support ES 1.2.0.
Changes in version 1.3.2.RELEASE (2015-12-18)
---------------------------------------------
* DATAES-223 - Release 1.3.2 (Gosling).
Changes in version 1.3.1.RELEASE (2015-11-15)
---------------------------------------------
* DATAES-212 - Release 1.3.1 (Gosling).
Changes in version 1.1.4.RELEASE (2015-10-14)
---------------------------------------------
* DATAES-202 - Release 1.1.4 (Evans).
Changes in version 1.3.0.RELEASE (2015-09-01)
---------------------------------------------
* DATAES-193 - Release 1.3 GA (Gosling).
* DATAES-137 - Should work out of the box with Spring Data REST.
Changes in version 1.3.0.RC1 (2015-08-04)
-----------------------------------------
* DATAES-186 - Release 1.3 RC1 (Gosling).
+2 -2
View File
@@ -1,5 +1,5 @@
Spring Data Elasticsearch 1.3 RC1
Copyright (c) [2013-2015] Pivotal Software, Inc.
Spring Data Elasticsearch 2.0.6
Copyright (c) [2013-2016] Pivotal Software, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License").
You may not use this product except in compliance with the License.
@@ -67,6 +67,27 @@
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="path-data" type="xsd:string" default="">
<xsd:annotation>
<xsd:documentation>
<![CDATA[ path to the data folder for node client ]]>
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="path-home" type="xsd:string" default="">
<xsd:annotation>
<xsd:documentation>
<![CDATA[ path to the home folder for node client ]]>
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="path-configuration" type="xsd:string" default="">
<xsd:annotation>
<xsd:documentation>
<![CDATA[ path to configuration file for node client ]]>
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
@@ -0,0 +1,80 @@
# Elasticsearch plugin descriptor file
# This file must exist as 'plugin-descriptor.properties' at
# the root directory of all plugins.
#
# A plugin can be 'site', 'jvm', or both.
#
### example site plugin for "foo":
#
# foo.zip <-- zip file for the plugin, with this structure:
# _site/ <-- the contents that will be served
# plugin-descriptor.properties <-- example contents below:
#
# site=true
# description=My cool plugin
# version=1.0
#
### example jvm plugin for "foo"
#
# foo.zip <-- zip file for the plugin, with this structure:
# <arbitrary name1>.jar <-- classes, resources, dependencies
# <arbitrary nameN>.jar <-- any number of jars
# plugin-descriptor.properties <-- example contents below:
#
# jvm=true
# classname=foo.bar.BazPlugin
# description=My cool plugin
# version=2.0.0-rc1
# elasticsearch.version=2.0
# java.version=1.7
#
### mandatory elements for all plugins:
#
# 'description': simple summary of the plugin
description=Groovy scripting integration for Elasticsearch
#
# 'version': plugin's version
version=2.2.0
#
# 'name': the plugin name
name=lang-groovy
### mandatory elements for site plugins:
#
# 'site': set to true to indicate contents of the _site/
# directory in the root of the plugin should be served.
site=false
#
### mandatory elements for jvm plugins :
#
# 'jvm': true if the 'classname' class should be loaded
# from jar files in the root directory of the plugin.
# Note that only jar files in the root directory are
# added to the classpath for the plugin! If you need
# other resources, package them into a resources jar.
jvm=true
#
# 'classname': the name of the class to load, fully-qualified.
classname=org.elasticsearch.script.groovy.GroovyPlugin
#
# 'java.version' version of java the code is built against
# use the system property java.specification.version
# version string must be a sequence of nonnegative decimal integers
# separated by "."'s and may have leading zeros
java.version=1.7
#
# 'elasticsearch.version' version of elasticsearch compiled against
# You will have to release a new version of the plugin for each new
# elasticsearch release. This version is checked when the plugin
# is loaded so Elasticsearch will refuse to start in the presence of
# plugins with the incorrect elasticsearch.version.
elasticsearch.version=2.2.0
#
### deprecated elements for jvm plugins :
#
# 'isolated': true if the plugin should have its own classloader.
# passing false is deprecated, and only intended to support plugins
# that have hard dependencies against each other. If this is
# not specified, then the plugin is isolated by default.
isolated=true
#
@@ -0,0 +1,57 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
grant {
// needed to generate runtime classes
permission java.lang.RuntimePermission "createClassLoader";
// needed by IndyInterface
permission java.lang.RuntimePermission "getClassLoader";
// needed by groovy engine
permission java.lang.RuntimePermission "accessClassInPackage.sun.reflect";
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
// needed by GroovyScriptEngineService to close its classloader (why?)
permission java.lang.RuntimePermission "closeClassLoader";
// Allow executing groovy scripts with codesource of /untrusted
permission groovy.security.GroovyCodeSourcePermission "/untrusted";
// Standard set of classes
permission org.elasticsearch.script.ClassPermission "<<STANDARD>>";
// groovy runtime
permission org.elasticsearch.script.ClassPermission "groovy.grape.GrabAnnotationTransformation";
permission org.elasticsearch.script.ClassPermission "groovy.json.JsonOutput";
permission org.elasticsearch.script.ClassPermission "groovy.lang.Binding";
permission org.elasticsearch.script.ClassPermission "groovy.lang.GroovyObject";
permission org.elasticsearch.script.ClassPermission "groovy.lang.GString";
permission org.elasticsearch.script.ClassPermission "groovy.lang.Script";
permission org.elasticsearch.script.ClassPermission "groovy.util.GroovyCollections";
permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.ast.builder.AstBuilderTransformation";
permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.reflection.ClassInfo";
permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.runtime.GStringImpl";
permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.runtime.powerassert.ValueRecorder";
permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.runtime.powerassert.AssertionRenderer";
permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.runtime.ScriptBytecodeAdapter";
permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation";
permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.vmplugin.v7.IndyInterface";
permission org.elasticsearch.script.ClassPermission "sun.reflect.ConstructorAccessorImpl";
permission org.elasticsearch.script.ClassPermission "groovy.lang.Closure";
permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.runtime.GeneratedClosure";
permission org.elasticsearch.script.ClassPermission "groovy.lang.MetaClass";
permission org.elasticsearch.script.ClassPermission "groovy.lang.Range";
};
@@ -0,0 +1,80 @@
# Elasticsearch plugin descriptor file
# This file must exist as 'plugin-descriptor.properties' at
# the root directory of all plugins.
#
# A plugin can be 'site', 'jvm', or both.
#
### example site plugin for "foo":
#
# foo.zip <-- zip file for the plugin, with this structure:
# _site/ <-- the contents that will be served
# plugin-descriptor.properties <-- example contents below:
#
# site=true
# description=My cool plugin
# version=1.0
#
### example jvm plugin for "foo"
#
# foo.zip <-- zip file for the plugin, with this structure:
# <arbitrary name1>.jar <-- classes, resources, dependencies
# <arbitrary nameN>.jar <-- any number of jars
# plugin-descriptor.properties <-- example contents below:
#
# jvm=true
# classname=foo.bar.BazPlugin
# description=My cool plugin
# version=2.0.0-rc1
# elasticsearch.version=2.0
# java.version=1.7
#
### mandatory elements for all plugins:
#
# 'description': simple summary of the plugin
description=Groovy scripting integration for Elasticsearch
#
# 'version': plugin's version
version=2.3.3
#
# 'name': the plugin name
name=lang-groovy
### mandatory elements for site plugins:
#
# 'site': set to true to indicate contents of the _site/
# directory in the root of the plugin should be served.
site=false
#
### mandatory elements for jvm plugins :
#
# 'jvm': true if the 'classname' class should be loaded
# from jar files in the root directory of the plugin.
# Note that only jar files in the root directory are
# added to the classpath for the plugin! If you need
# other resources, package them into a resources jar.
jvm=true
#
# 'classname': the name of the class to load, fully-qualified.
classname=org.elasticsearch.script.groovy.GroovyPlugin
#
# 'java.version' version of java the code is built against
# use the system property java.specification.version
# version string must be a sequence of nonnegative decimal integers
# separated by "."'s and may have leading zeros
java.version=1.7
#
# 'elasticsearch.version' version of elasticsearch compiled against
# You will have to release a new version of the plugin for each new
# elasticsearch release. This version is checked when the plugin
# is loaded so Elasticsearch will refuse to start in the presence of
# plugins with the incorrect elasticsearch.version.
elasticsearch.version=2.3.3
#
### deprecated elements for jvm plugins :
#
# 'isolated': true if the plugin should have its own classloader.
# passing false is deprecated, and only intended to support plugins
# that have hard dependencies against each other. If this is
# not specified, then the plugin is isolated by default.
isolated=true
#
@@ -0,0 +1,58 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
grant {
// needed to generate runtime classes
permission java.lang.RuntimePermission "createClassLoader";
// needed by IndyInterface
permission java.lang.RuntimePermission "getClassLoader";
// needed by groovy engine
permission java.lang.RuntimePermission "accessClassInPackage.sun.reflect";
// needed by GroovyScriptEngineService to close its classloader (why?)
permission java.lang.RuntimePermission "closeClassLoader";
// Allow executing groovy scripts with codesource of /untrusted
permission groovy.security.GroovyCodeSourcePermission "/untrusted";
// Standard set of classes
permission org.elasticsearch.script.ClassPermission "<<STANDARD>>";
// groovy runtime (TODO: clean these up if possible)
permission org.elasticsearch.script.ClassPermission "groovy.grape.GrabAnnotationTransformation";
permission org.elasticsearch.script.ClassPermission "groovy.json.JsonOutput";
permission org.elasticsearch.script.ClassPermission "groovy.lang.Binding";
permission org.elasticsearch.script.ClassPermission "groovy.lang.GroovyObject";
permission org.elasticsearch.script.ClassPermission "groovy.lang.GString";
permission org.elasticsearch.script.ClassPermission "groovy.lang.Script";
permission org.elasticsearch.script.ClassPermission "groovy.util.GroovyCollections";
permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.ast.builder.AstBuilderTransformation";
permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.reflection.ClassInfo";
permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.runtime.GStringImpl";
permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.runtime.powerassert.ValueRecorder";
permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.runtime.powerassert.AssertionRenderer";
permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.runtime.ScriptBytecodeAdapter";
permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation";
permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.vmplugin.v7.IndyInterface";
permission org.elasticsearch.script.ClassPermission "sun.reflect.ConstructorAccessorImpl";
permission org.elasticsearch.script.ClassPermission "sun.reflect.MethodAccessorImpl";
permission org.elasticsearch.script.ClassPermission "groovy.lang.Closure";
permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.runtime.GeneratedClosure";
permission org.elasticsearch.script.ClassPermission "groovy.lang.MetaClass";
permission org.elasticsearch.script.ClassPermission "groovy.lang.Range";
permission org.elasticsearch.script.ClassPermission "groovy.lang.Reference";
};
@@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* Copyright 2014-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -50,7 +50,7 @@ public class InnerObjectTests {
elasticsearchTemplate.deleteIndex(Book.class);
elasticsearchTemplate.createIndex(Book.class);
elasticsearchTemplate.putMapping(Book.class);
elasticsearchTemplate.refresh(Book.class, true);
elasticsearchTemplate.refresh(Book.class);
}
@Test
@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -48,6 +48,7 @@ import org.springframework.data.elasticsearch.entities.Car;
import org.springframework.data.elasticsearch.entities.GirlFriend;
import org.springframework.data.elasticsearch.entities.Person;
import org.springframework.data.elasticsearch.entities.PersonMultipleLevelNested;
import org.springframework.data.geo.Point;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -69,15 +70,15 @@ public class NestedObjectTests {
elasticsearchTemplate.deleteIndex(Book.class);
elasticsearchTemplate.createIndex(Book.class);
elasticsearchTemplate.putMapping(Book.class);
elasticsearchTemplate.refresh(Book.class, true);
elasticsearchTemplate.refresh(Book.class);
elasticsearchTemplate.deleteIndex(Person.class);
elasticsearchTemplate.createIndex(Person.class);
elasticsearchTemplate.putMapping(Person.class);
elasticsearchTemplate.refresh(Person.class, true);
elasticsearchTemplate.refresh(Person.class);
elasticsearchTemplate.deleteIndex(PersonMultipleLevelNested.class);
elasticsearchTemplate.createIndex(PersonMultipleLevelNested.class);
elasticsearchTemplate.putMapping(PersonMultipleLevelNested.class);
elasticsearchTemplate.refresh(PersonMultipleLevelNested.class, true);
elasticsearchTemplate.refresh(PersonMultipleLevelNested.class);
}
@Test
@@ -129,7 +130,7 @@ public class NestedObjectTests {
elasticsearchTemplate.putMapping(Person.class);
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(Person.class, true);
elasticsearchTemplate.refresh(Person.class);
final QueryBuilder builder = nestedQuery("car", boolQuery().must(termQuery("car.name", "saturn")).must(termQuery("car.model", "imprezza")));
@@ -147,7 +148,7 @@ public class NestedObjectTests {
//when
elasticsearchTemplate.putMapping(PersonMultipleLevelNested.class);
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(PersonMultipleLevelNested.class, true);
elasticsearchTemplate.refresh(PersonMultipleLevelNested.class);
//then
final GetQuery getQuery = new GetQuery();
@@ -184,7 +185,7 @@ public class NestedObjectTests {
//when
elasticsearchTemplate.putMapping(PersonMultipleLevelNested.class);
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(PersonMultipleLevelNested.class, true);
elasticsearchTemplate.refresh(PersonMultipleLevelNested.class);
//then
final BoolQueryBuilder builder = boolQuery();
@@ -325,7 +326,7 @@ public class NestedObjectTests {
elasticsearchTemplate.putMapping(Person.class);
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(Person.class, true);
elasticsearchTemplate.refresh(Person.class);
final QueryBuilder builder = nestedQuery("books", boolQuery().must(termQuery("books.name", "java")));
@@ -372,7 +373,7 @@ public class NestedObjectTests {
indexQueries.add(indexQuery2);
//when
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(Book.class, true);
elasticsearchTemplate.refresh(Book.class);
//then
final SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(nestedQuery("buckets", termQuery("buckets.1", "test3")))
@@ -0,0 +1,139 @@
/*
* Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.elasticsearch;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Version;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.ScriptedField;
/**
* @author Rizwan Idrees
* @author Mohsin Husen
*/
@Document(indexName = "test-index", type = "test-type", shards = 1, replicas = 0, refreshInterval = "-1")
public class SampleEntity {
@Id
private String id;
private String type;
private String message;
private int rate;
@ScriptedField
private Long scriptedRate;
private boolean available;
private String highlightedMessage;
@Version
private Long version;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getRate() {
return rate;
}
public void setRate(int rate) {
this.rate = rate;
}
public Long getScriptedRate() {
return scriptedRate;
}
public void setScriptedRate(Long scriptedRate) {
this.scriptedRate = scriptedRate;
}
public boolean isAvailable() {
return available;
}
public void setAvailable(boolean available) {
this.available = available;
}
public String getHighlightedMessage() {
return highlightedMessage;
}
public void setHighlightedMessage(String highlightedMessage) {
this.highlightedMessage = highlightedMessage;
}
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof SampleEntity)) {
return false;
}
if (this == obj) {
return true;
}
SampleEntity rhs = (SampleEntity) obj;
return new EqualsBuilder().append(this.id, rhs.id).append(this.type, rhs.type).append(this.message, rhs.message)
.append(this.rate, rhs.rate).append(this.available, rhs.available).append(this.version, rhs.version).isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder().append(id).append(type).append(message).append(rate).append(available).append(version)
.toHashCode();
}
@Override
public String toString() {
return "SampleEntity{" +
"id='" + id + '\'' +
", type='" + type + '\'' +
", message='" + message + '\'' +
", rate=" + rate +
", available=" + available +
", highlightedMessage='" + highlightedMessage + '\'' +
", version=" + version +
'}';
}
}
@@ -20,6 +20,7 @@ import static org.junit.Assert.*;
import org.elasticsearch.index.query.QueryBuilders;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -49,6 +50,7 @@ public class SpELEntityTests {
repository.deleteAll();
}
@Ignore("DATAES-211")
@Test
public void shouldDo() {
// Given
@@ -63,6 +65,7 @@ public class SpELEntityTests {
assertThat(count, is(2L));
}
@Ignore("DATAES-211")
@Test
public void shouldSupportSpelInType() {
// Given
@@ -0,0 +1,38 @@
/*
* 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;
import static org.elasticsearch.node.NodeBuilder.*;
import java.util.UUID;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings;
/**
* @author Mohsin Husen
*/
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", "target/test-home-dir"))
.clusterName(UUID.randomUUID().toString()).local(true).node()
.client();
}
}
@@ -1,75 +0,0 @@
/*
* 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.builder;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.entities.SampleEntity;
/**
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
*/
public class SampleEntityBuilder {
private SampleEntity result;
public SampleEntityBuilder(String id) {
result = new SampleEntity();
result.setId(id);
}
public SampleEntityBuilder type(String type) {
result.setType(type);
return this;
}
public SampleEntityBuilder message(String message) {
result.setMessage(message);
return this;
}
public SampleEntityBuilder rate(int rate) {
result.setRate(rate);
return this;
}
public SampleEntityBuilder available(boolean available) {
result.setAvailable(available);
return this;
}
public SampleEntityBuilder highlightedMessage(String highlightedMessage) {
result.setHighlightedMessage(highlightedMessage);
return this;
}
public SampleEntityBuilder version(Long version) {
result.setVersion(version);
return this;
}
public SampleEntity build() {
return result;
}
public IndexQuery buildIndex() {
IndexQuery indexQuery = new IndexQuery();
indexQuery.setId(result.getId());
indexQuery.setObject(result);
return indexQuery;
}
}
@@ -1,60 +0,0 @@
/*
* 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.builder;
import java.math.BigDecimal;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.entities.StockPrice;
/**
* @author Artur Konczak
* @author Mohsin Husen
*/
public class StockPriceBuilder {
private StockPrice result;
public StockPriceBuilder(String id) {
result = new StockPrice(id);
}
public StockPriceBuilder symbol(String symbol) {
result.setSymbol(symbol);
return this;
}
public StockPriceBuilder price(BigDecimal price) {
result.setPrice(price);
return this;
}
public StockPriceBuilder price(double price) {
result.setPrice(new BigDecimal(price));
return this;
}
public StockPrice build() {
return result;
}
public IndexQuery buildIndex() {
IndexQuery indexQuery = new IndexQuery();
indexQuery.setId(result.getId());
indexQuery.setObject(result);
return indexQuery;
}
}
@@ -15,7 +15,6 @@
*/
package org.springframework.data.elasticsearch.config;
import static org.elasticsearch.node.NodeBuilder.*;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
@@ -27,6 +26,7 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.Utils;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.entities.SampleEntity;
@@ -60,7 +60,7 @@ public class EnableElasticsearchRepositoriesTests implements ApplicationContextA
@Bean
public ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchTemplate(nodeBuilder().local(true).clusterName("testCluster2").node().client());
return new ElasticsearchTemplate(Utils.getNodeClient());
}
}
@@ -20,6 +20,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.Utils;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.entities.SampleEntity;
@@ -28,7 +29,6 @@ import org.springframework.data.repository.Repository;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.elasticsearch.node.NodeBuilder.nodeBuilder;
import static org.junit.Assert.assertNotNull;
/**
@@ -45,7 +45,7 @@ public class EnableNestedElasticsearchRepositoriesTests {
@Bean
public ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchTemplate(nodeBuilder().local(true).clusterName("testCluster2").node().client());
return new ElasticsearchTemplate(Utils.getNodeClient());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* Copyright 2014-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,16 +19,14 @@ import static org.apache.commons.lang.RandomStringUtils.*;
import static org.elasticsearch.index.query.QueryBuilders.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.builder.SampleEntityBuilder;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.data.elasticsearch.entities.SampleEntity;
import org.springframework.test.context.ContextConfiguration;
@@ -41,7 +39,8 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@ContextConfiguration("classpath:elasticsearch-template-test.xml")
public class AliasTests {
private static final String INDEX_NAME = "test-alias-index";
private static final String INDEX_NAME_1 = "test-alias-index-1";
private static final String INDEX_NAME_2 = "test-alias-index-2";
private static final String TYPE_NAME = "test-alias-type";
@Autowired
@@ -53,11 +52,15 @@ public class AliasTests {
settings.put("index.refresh_interval", "-1");
settings.put("index.number_of_replicas", "0");
settings.put("index.number_of_shards", "2");
settings.put("index.store.type", "memory");
settings.put("index.store.type", "fs");
elasticsearchTemplate.deleteIndex(INDEX_NAME);
elasticsearchTemplate.createIndex(INDEX_NAME, settings);
elasticsearchTemplate.refresh(INDEX_NAME, true);
elasticsearchTemplate.deleteIndex(INDEX_NAME_1);
elasticsearchTemplate.createIndex(INDEX_NAME_1, settings);
elasticsearchTemplate.refresh(INDEX_NAME_1);
elasticsearchTemplate.deleteIndex(INDEX_NAME_2);
elasticsearchTemplate.createIndex(INDEX_NAME_2, settings);
elasticsearchTemplate.refresh(INDEX_NAME_2);
}
@Test
@@ -65,34 +68,33 @@ public class AliasTests {
// given
String aliasName = "test-alias";
AliasQuery aliasQuery = new AliasBuilder()
.withIndexName(INDEX_NAME)
.withIndexName(INDEX_NAME_1)
.withAliasName(aliasName).build();
// when
elasticsearchTemplate.addAlias(aliasQuery);
// then
Set<String> aliases = elasticsearchTemplate.queryForAlias(INDEX_NAME);
List<AliasMetaData> aliases = elasticsearchTemplate.queryForAlias(INDEX_NAME_1);
assertThat(aliases, is(notNullValue()));
assertThat(aliases.contains(aliasName), is(true));
assertThat(aliases.get(0).alias(), is(aliasName));
}
@Test
public void shouldRemoveAlias() {
// given
String indexName = INDEX_NAME;
String indexName = INDEX_NAME_1;
String aliasName = "test-alias";
AliasQuery aliasQuery = new AliasBuilder()
.withIndexName(indexName)
.withAliasName(aliasName).build();
// when
elasticsearchTemplate.addAlias(aliasQuery);
Set<String> aliases = elasticsearchTemplate.queryForAlias(indexName);
List<AliasMetaData> aliases = elasticsearchTemplate.queryForAlias(indexName);
assertThat(aliases, is(notNullValue()));
assertThat(aliases.contains(aliasName), is(true));
assertThat(aliases.get(0).alias(), is(aliasName));
// then
elasticsearchTemplate.removeAlias(aliasQuery);
aliases = elasticsearchTemplate.queryForAlias(indexName);
assertThat(aliases, is(notNullValue()));
assertThat(aliases.size(), is(0));
assertThat(aliases, is(nullValue()));
}
/*
@@ -101,7 +103,7 @@ public class AliasTests {
@Test
public void shouldAddAliasWithGivenRoutingValue() {
//given
String indexName = INDEX_NAME;
String indexName = INDEX_NAME_1;
String alias = "test-alias";
AliasQuery aliasQuery = new AliasBuilder()
@@ -113,7 +115,7 @@ public class AliasTests {
elasticsearchTemplate.addAlias(aliasQuery);
String documentId = randomNumeric(5);
SampleEntity sampleEntity = new SampleEntityBuilder(documentId)
SampleEntity sampleEntity = SampleEntity.builder().id(documentId)
.message("some message")
.version(System.currentTimeMillis()).build();
@@ -125,15 +127,17 @@ public class AliasTests {
.build();
elasticsearchTemplate.index(indexQuery);
elasticsearchTemplate.refresh(INDEX_NAME, true);
elasticsearchTemplate.refresh(INDEX_NAME_1);
SearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
.withIndices(alias).withTypes(TYPE_NAME).build();
long count = elasticsearchTemplate.count(query);
//then
Set<String> aliases = elasticsearchTemplate.queryForAlias(INDEX_NAME);
List<AliasMetaData> aliases = elasticsearchTemplate.queryForAlias(INDEX_NAME_1);
assertThat(aliases, is(notNullValue()));
assertThat(aliases.contains(alias), is(true));
assertThat(aliases.get(0).alias(), is(alias));
assertThat(aliases.get(0).searchRouting(), is("0"));
assertThat(aliases.get(0).indexRouting(), is("0"));
assertThat(count, is(1L));
//cleanup
@@ -141,7 +145,7 @@ public class AliasTests {
elasticsearchTemplate.deleteIndex(SampleEntity.class);
elasticsearchTemplate.createIndex(SampleEntity.class);
elasticsearchTemplate.putMapping(SampleEntity.class);
elasticsearchTemplate.refresh(SampleEntity.class, true);
elasticsearchTemplate.refresh(SampleEntity.class);
}
/*
@@ -154,12 +158,12 @@ public class AliasTests {
String alias2 = "test-alias-2";
AliasQuery aliasQuery1 = new AliasBuilder()
.withIndexName(INDEX_NAME)
.withIndexName(INDEX_NAME_1)
.withAliasName(alias1)
.withIndexRouting("0").build();
AliasQuery aliasQuery2 = new AliasBuilder()
.withIndexName(INDEX_NAME)
.withIndexName(INDEX_NAME_2)
.withAliasName(alias2)
.withSearchRouting("1").build();
@@ -168,7 +172,7 @@ public class AliasTests {
elasticsearchTemplate.addAlias(aliasQuery2);
String documentId = randomNumeric(5);
SampleEntity sampleEntity = new SampleEntityBuilder(documentId)
SampleEntity sampleEntity = SampleEntity.builder().id(documentId)
.message("some message")
.version(System.currentTimeMillis()).build();
@@ -179,24 +183,21 @@ public class AliasTests {
.withObject(sampleEntity).build();
elasticsearchTemplate.index(indexQuery);
elasticsearchTemplate.refresh(SampleEntity.class, true);
SearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
.withIndices(alias2).withTypes(TYPE_NAME).build();
long count = elasticsearchTemplate.count(query, SampleEntity.class);
// then
Set<String> aliases = elasticsearchTemplate.queryForAlias(INDEX_NAME);
assertThat(aliases, is(notNullValue()));
assertThat(aliases.contains(alias1), is(true));
assertThat(aliases.contains(alias2), is(true));
assertThat(count, is(0L));
List<AliasMetaData> responseAlias1 = elasticsearchTemplate.queryForAlias(INDEX_NAME_1);
assertThat(responseAlias1, is(notNullValue()));
assertThat(responseAlias1.get(0).alias(), is(alias1));
assertThat(responseAlias1.get(0).indexRouting(), is("0"));
List<AliasMetaData> responseAlias2 = elasticsearchTemplate.queryForAlias(INDEX_NAME_2);
assertThat(responseAlias2, is(notNullValue()));
assertThat(responseAlias2.get(0).alias(), is(alias2));
assertThat(responseAlias2.get(0).searchRouting(), is("1"));
//cleanup
elasticsearchTemplate.removeAlias(aliasQuery1);
elasticsearchTemplate.removeAlias(aliasQuery2);
elasticsearchTemplate.deleteIndex(SampleEntity.class);
elasticsearchTemplate.createIndex(SampleEntity.class);
elasticsearchTemplate.putMapping(SampleEntity.class);
elasticsearchTemplate.refresh(SampleEntity.class, true);
}
}
@@ -20,6 +20,7 @@ import java.util.LinkedList;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
/**
@@ -46,7 +47,7 @@ public class CustomResultMapper implements ResultsMapper {
}
@Override
public <T> FacetedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
public <T> Page<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@@ -19,11 +19,14 @@ import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.io.IOException;
import java.util.Locale;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.elasticsearch.builder.CarBuilder;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.elasticsearch.entities.Car;
import org.springframework.data.elasticsearch.entities.GeoEntity;
import org.springframework.data.geo.Point;
/**
* @author Artur Konczak
@@ -46,7 +49,7 @@ public class DefaultEntityMapperTests {
//Given
//When
String jsonResult = entityMapper.mapToString(new CarBuilder().model(CAR_MODEL).name(CAR_NAME).build());
String jsonResult = entityMapper.mapToString(Car.builder().model(CAR_MODEL).name(CAR_NAME).build());
//Then
assertThat(jsonResult, is(JSON_STRING));
@@ -63,4 +66,28 @@ public class DefaultEntityMapperTests {
assertThat(result.getName(), is(CAR_NAME));
assertThat(result.getModel(), is(CAR_MODEL));
}
@Test
public void shouldMapGeoPointElasticsearchNames() throws IOException {
//given
final Point point = new Point(10, 20);
final int radius = 10;
final String pointAsString = point.getX() + "," + point.getY();
final double[] pointAsArray = {point.getX(), point.getY()};
final GeoEntity geoEntity = GeoEntity.builder()
.pointA(point).pointB(GeoPoint.fromPoint(point)).pointC(pointAsString).pointD(pointAsArray)
.build();
//when
String jsonResult = entityMapper.mapToString(geoEntity);
//then
assertThat(jsonResult, containsString(pointTemplate("pointA", point)));
assertThat(jsonResult, containsString(pointTemplate("pointB", point)));
assertThat(jsonResult, containsString(String.format(Locale.ENGLISH, "\"%s\":\"%s\"", "pointC", pointAsString)));
assertThat(jsonResult, containsString(String.format(Locale.ENGLISH, "\"%s\":[%.1f,%.1f]", "pointD", pointAsArray[0], pointAsArray[1])));
}
private String pointTemplate(String name, Point point) {
return String.format(Locale.ENGLISH, "\"%s\":{\"lat\":%.1f,\"lon\":%.1f}", name, point.getX(), point.getY());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors.
* Copyright 2013-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,11 +19,13 @@ import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.collections.iterators.ArrayIterator;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.SearchHit;
@@ -34,8 +36,13 @@ import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.data.domain.Page;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import org.springframework.data.elasticsearch.entities.Car;
import com.fasterxml.jackson.databind.util.ArrayIterator;
/**
* @author Artur Konczak
* @author Mohsin Husen
@@ -50,7 +57,7 @@ public class DefaultResultMapperTests {
@Before
public void init() {
MockitoAnnotations.initMocks(this);
resultMapper = new DefaultResultMapper();
resultMapper = new DefaultResultMapper(new SimpleElasticsearchMappingContext());
}
@Test
@@ -63,7 +70,7 @@ public class DefaultResultMapperTests {
when(response.getHits()).thenReturn(searchHits);
//When
FacetedPage<Car> page = resultMapper.mapResults(response, Car.class, null);
Page<Car> page = resultMapper.mapResults(response, Car.class, null);
//Then
assertThat(page.hasContent(), is(true));
@@ -81,7 +88,7 @@ public class DefaultResultMapperTests {
when(response.getHits()).thenReturn(searchHits);
//When
FacetedPage<Car> page = resultMapper.mapResults(response, Car.class, null);
Page<Car> page = resultMapper.mapResults(response, Car.class, null);
//Then
assertThat(page.hasContent(), is(true));
@@ -103,6 +110,22 @@ public class DefaultResultMapperTests {
assertThat(result.getModel(), is("Grat"));
assertThat(result.getName(), is("Ford"));
}
/**
* @see DATAES-281.
*/
@Test
public void setsIdentifierOnImmutableType() {
GetResponse response = mock(GetResponse.class);
when(response.getSourceAsString()).thenReturn("{}");
when(response.getId()).thenReturn("identifier");
ImmutableEntity result = resultMapper.mapResult(response, ImmutableEntity.class);
assertThat(result, is(notNullValue()));
assertThat(result.getId(), is("identifier"));
}
private SearchHit createCarHit(String name, String model) {
SearchHit hit = mock(SearchHit.class);
@@ -131,4 +154,12 @@ public class DefaultResultMapperTests {
result.put("model", new InternalSearchHitField("model", Arrays.<Object>asList(model)));
return result;
}
@Document(indexName = "someIndex")
@NoArgsConstructor(force = true)
@Getter
static class ImmutableEntity {
private final String id, name;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* Copyright 2014-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,12 +15,17 @@
*/
package org.springframework.data.elasticsearch.core;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.index.query.QueryBuilders.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.util.List;
import org.elasticsearch.action.RoutingMissingException;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.junit.After;
@@ -30,6 +35,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.UpdateQuery;
import org.springframework.data.elasticsearch.entities.ParentEntity;
import org.springframework.data.elasticsearch.entities.ParentEntity.ChildEntity;
import org.springframework.test.context.ContextConfiguration;
@@ -50,7 +56,6 @@ public class ElasticsearchTemplateParentChildTests {
clean();
elasticsearchTemplate.createIndex(ParentEntity.class);
elasticsearchTemplate.createIndex(ChildEntity.class);
elasticsearchTemplate.putMapping(ParentEntity.class);
elasticsearchTemplate.putMapping(ChildEntity.class);
}
@@ -71,8 +76,8 @@ public class ElasticsearchTemplateParentChildTests {
index("child1", parent1.getId(), child1name);
index("child2", parent2.getId(), "Second");
elasticsearchTemplate.refresh(ParentEntity.class, true);
elasticsearchTemplate.refresh(ChildEntity.class, true);
elasticsearchTemplate.refresh(ParentEntity.class);
elasticsearchTemplate.refresh(ChildEntity.class);
// find all parents that have the first child
QueryBuilder query = hasChildQuery(ParentEntity.CHILD_TYPE, QueryBuilders.termQuery("name", child1name.toLowerCase()));
@@ -83,25 +88,52 @@ public class ElasticsearchTemplateParentChildTests {
}
@Test
public void shouldSearchTopChildrenForGivenParent() {
// index two parents
ParentEntity parent1 = index("parent1", "First Parent");
ParentEntity parent2 = index("parent2", "Second Parent");
public void shouldUpdateChild() throws Exception {
// index parent and child
ParentEntity parent = index("parent", "Parent");
ChildEntity child = index("child", parent.getId(), "Child");
String newChildName = "New Child Name";
// index a child for each parent
String child1name = "First";
index("child1", parent1.getId(), child1name);
index("child2", parent2.getId(), "Second");
// update the child, not forgetting to set the parent id as routing parameter
UpdateRequest updateRequest = new UpdateRequest(ParentEntity.INDEX, ParentEntity.CHILD_TYPE, child.getId());
updateRequest.routing(parent.getId());
XContentBuilder builder;
builder = jsonBuilder().startObject().field("name", newChildName).endObject();
updateRequest.doc(builder);
final UpdateResponse response = update(updateRequest);
elasticsearchTemplate.refresh(ParentEntity.class, true);
elasticsearchTemplate.refresh(ChildEntity.class, true);
assertThat(response.getShardInfo().getSuccessful(), is(1));
}
// find all parents that have the first child using topChildren Query
QueryBuilder query = topChildrenQuery(ParentEntity.CHILD_TYPE, QueryBuilders.termQuery("name", child1name.toLowerCase()));
List<ParentEntity> parents = elasticsearchTemplate.queryForList(new NativeSearchQuery(query), ParentEntity.class);
@Test(expected = RoutingMissingException.class)
public void shouldFailWithRoutingMissingExceptionOnUpdateChildIfNotRoutingSetOnUpdateRequest() throws Exception {
// index parent and child
ParentEntity parent = index("parent", "Parent");
ChildEntity child = index("child", parent.getId(), "Child");
String newChildName = "New Child Name";
// we're expecting only the first parent as result
assertThat("parents", parents, contains(hasProperty("id", is(parent1.getId()))));
// update the child, forget routing parameter
UpdateRequest updateRequest = new UpdateRequest(ParentEntity.INDEX, ParentEntity.CHILD_TYPE, child.getId());
XContentBuilder builder;
builder = jsonBuilder().startObject().field("name", newChildName).endObject();
updateRequest.doc(builder);
update(updateRequest);
}
@Test(expected = RoutingMissingException.class)
public void shouldFailWithRoutingMissingExceptionOnUpdateChildIfRoutingOnlySetOnRequestDoc() throws Exception {
// index parent and child
ParentEntity parent = index("parent", "Parent");
ChildEntity child = index("child", parent.getId(), "Child");
String newChildName = "New Child Name";
// update the child
UpdateRequest updateRequest = new UpdateRequest(ParentEntity.INDEX, ParentEntity.CHILD_TYPE, child.getId());
XContentBuilder builder;
builder = jsonBuilder().startObject().field("name", newChildName).endObject();
updateRequest.doc(builder);
updateRequest.doc().routing(parent.getId());
update(updateRequest);
}
private ParentEntity index(String parentId, String name) {
@@ -124,4 +156,13 @@ public class ElasticsearchTemplateParentChildTests {
return child;
}
private UpdateResponse update(UpdateRequest updateRequest) {
final UpdateQuery update = new UpdateQuery();
update.setId(updateRequest.id());
update.setType(updateRequest.type());
update.setIndexName(updateRequest.index());
update.setUpdateRequest(updateRequest);
return elasticsearchTemplate.update(update);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* Copyright 2014-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -71,7 +71,7 @@ public class LogEntityTests {
.ip("10.10.10.4").buildIndex();
template.bulkIndex(Arrays.asList(indexQuery1, indexQuery2, indexQuery3, indexQuery4));
template.refresh(LogEntity.class, true);
template.refresh(LogEntity.class);
}
/*
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors.
* Copyright 2013-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ package org.springframework.data.elasticsearch.core;
import static org.elasticsearch.index.query.QueryBuilders.*;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.springframework.data.elasticsearch.utils.IndexBuilder.*;
import java.io.IOException;
import java.math.BigDecimal;
@@ -30,10 +31,10 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.builder.SampleInheritedEntityBuilder;
import org.springframework.data.elasticsearch.builder.StockPriceBuilder;
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.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -59,8 +60,8 @@ public class MappingBuilderTests {
@Test
public void testInfiniteLoopAvoidance() throws IOException {
final String expected = "{\"mapping\":{\"properties\":{\"message\":{\"store\":true,\"" +
"type\":\"string\",\"index\":\"not_analyzed\",\"search_analyzer\":\"standard\"," +
"\"index_analyzer\":\"standard\"}}}}";
"type\":\"string\",\"index\":\"not_analyzed\"," +
"\"analyzer\":\"standard\"}}}}";
XContentBuilder xContentBuilder = MappingBuilder.buildMapping(SampleTransientEntity.class, "mapping", "id", null);
assertThat(xContentBuilder.string(), is(expected));
@@ -89,8 +90,8 @@ public class MappingBuilderTests {
String symbol = "AU";
double price = 2.34;
String id = "abc";
elasticsearchTemplate.index(new StockPriceBuilder(id).symbol(symbol).price(price).buildIndex());
elasticsearchTemplate.refresh(StockPrice.class, true);
elasticsearchTemplate.index(buildIndex(StockPrice.builder().id(id).symbol(symbol).price(new BigDecimal(price)).build()));
elasticsearchTemplate.refresh(StockPrice.class);
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build();
List<StockPrice> result = elasticsearchTemplate.queryForList(searchQuery, StockPrice.class);
@@ -114,8 +115,8 @@ public class MappingBuilderTests {
@Test
public void shouldBuildMappingWithSuperclass() throws IOException {
final String expected = "{\"mapping\":{\"properties\":{\"message\":{\"store\":true,\"" +
"type\":\"string\",\"index\":\"not_analyzed\",\"search_analyzer\":\"standard\"," +
"\"index_analyzer\":\"standard\"},\"createdDate\":{\"store\":false," +
"type\":\"string\",\"index\":\"not_analyzed\",\"analyzer\":\"standard\"}" +
",\"createdDate\":{\"store\":false," +
"\"type\":\"date\",\"index\":\"not_analyzed\"}}}}";
XContentBuilder xContentBuilder = MappingBuilder.buildMapping(SampleInheritedEntity.class, "mapping", "id", null);
@@ -137,7 +138,7 @@ public class MappingBuilderTests {
String message = "msg";
String id = "abc";
elasticsearchTemplate.index(new SampleInheritedEntityBuilder(id).createdDate(createdDate).message(message).buildIndex());
elasticsearchTemplate.refresh(SampleInheritedEntity.class, true);
elasticsearchTemplate.refresh(SampleInheritedEntity.class);
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build();
List<SampleInheritedEntity> result = elasticsearchTemplate.queryForList(searchQuery, SampleInheritedEntity.class);
@@ -147,4 +148,20 @@ public class MappingBuilderTests {
assertThat(entry.getCreatedDate(), is(createdDate));
assertThat(entry.getMessage(), is(message));
}
@Test
public void shouldBuildMappingsForGeoPoint() throws IOException {
//given
//when
XContentBuilder xContentBuilder = MappingBuilder.buildMapping(GeoEntity.class, "mapping", "id", null);
//then
final String result = xContentBuilder.string();
assertThat(result, containsString("\"pointA\":{\"type\":\"geo_point\""));
assertThat(result, containsString("\"pointB\":{\"type\":\"geo_point\""));
assertThat(result, containsString("\"pointC\":{\"type\":\"geo_point\""));
assertThat(result, containsString("\"pointD\":{\"type\":\"geo_point\""));
}
}
@@ -27,11 +27,10 @@ import org.springframework.data.elasticsearch.entities.SampleDateMappingEntity;
* @author Jakub Vavrik
* @author Mohsin Husen
*/
public class SimpleElasticsearchDateMappingTest {
public class SimpleElasticsearchDateMappingTests {
private static final String EXPECTED_MAPPING = "{\"mapping\":{\"properties\":{\"message\":{\"store\":true," +
"\"type\":\"string\",\"index\":\"not_analyzed\",\"search_analyzer\":\"standard\",\"index_analyzer\"" +
":\"standard\"},\"customFormatDate\":{\"store\":false,\"type\":\"date\",\"format\":\"dd.MM.yyyy hh:mm\"}," +
"\"type\":\"string\",\"index\":\"not_analyzed\",\"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\"}}}}";

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