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

Compare commits

...

180 Commits

Author SHA1 Message Date
Mark Paluch cef1fc7d77 DATAES-489 - Release version 3.1.2 (Lovelace SR2). 2018-10-29 12:53:52 +01:00
Mark Paluch 9ddf4868ef DATAES-489 - Prepare 3.1.2 (Lovelace SR2). 2018-10-29 12:52:55 +01:00
Mark Paluch dde561a805 DATAES-489 - Updated changelog. 2018-10-29 12:52:52 +01:00
Mark Paluch 950c48a069 DATAES-484 - Updated changelog. 2018-10-15 14:19:08 +02:00
Mark Paluch df9954b3ef DATAES-485 - Updated changelog. 2018-10-15 12:46:30 +02:00
Mark Paluch 32d5f5dcb9 DATAES-486 - After release cleanups. 2018-10-15 11:12:14 +02:00
Mark Paluch 0191d69d94 DATAES-486 - Prepare next development iteration. 2018-10-15 11:12:13 +02:00
Mark Paluch e7e0983ea5 DATAES-486 - Release version 3.1.1 (Lovelace SR1). 2018-10-15 10:42:05 +02:00
Mark Paluch a299260a03 DATAES-486 - Prepare 3.1.1 (Lovelace SR1). 2018-10-15 10:40:57 +02:00
Mark Paluch 627d96cbfc DATAES-486 - Updated changelog. 2018-10-15 10:40:56 +02:00
Mark Paluch efa3b4d17e DATAES-480 - After release cleanups. 2018-09-21 07:46:18 -04:00
Mark Paluch f5d44ad755 DATAES-480 - Prepare next development iteration. 2018-09-21 07:46:17 -04:00
Mark Paluch 5a50114b73 DATAES-480 - Release version 3.1 GA (Lovelace). 2018-09-21 07:08:39 -04:00
Mark Paluch 45a9384d4f DATAES-480 - Prepare 3.1 GA (Lovelace). 2018-09-21 07:07:51 -04:00
Mark Paluch 789acdc3dc DATAES-480 - Updated changelog. 2018-09-21 07:07:49 -04:00
Mark Paluch 946a60d24d DATAES-473 - Updated changelog. 2018-09-10 14:15:51 +02:00
Mark Paluch 838776dd63 DATAES-474 - Updated changelog. 2018-09-10 10:20:58 +02:00
jnizet b8324f9205 DATAES-479 - Allow specifying a HighlightBuilder when creating a query.
Original pull request: #217.
2018-08-24 15:59:12 +02:00
Oliver Gierke 94d18e8111 DATAES-472 - After release cleanups. 2018-08-20 10:56:53 +02:00
Oliver Gierke a1aa755253 DATAES-472 - Prepare next development iteration. 2018-08-20 10:56:52 +02:00
Oliver Gierke dfd9d962d3 DATAES-472 - Release version 3.1 RC2 (Lovelace). 2018-08-20 10:40:11 +02:00
Oliver Gierke e1d3f6f160 DATAES-472 - Prepare 3.1 RC2 (Lovelace). 2018-08-20 10:39:43 +02:00
Oliver Gierke 7bb108c998 DATAES-472 - Updated changelog. 2018-08-20 10:39:41 +02:00
Mark Paluch d1b71f2e73 DATAES-463 - Updated changelog. 2018-07-27 11:45:25 +02:00
Mark Paluch 88fe60c7d4 DATAES-465 - Updated changelog. 2018-07-26 16:23:57 +02:00
Mark Paluch 9a0a931ce2 DATAES-452 - After release cleanups. 2018-07-26 12:32:29 +02:00
Mark Paluch 02f2171cb6 DATAES-452 - Prepare next development iteration. 2018-07-26 12:32:25 +02:00
Mark Paluch 5d4cabae10 DATAES-452 - Release version 3.1 RC1 (Lovelace). 2018-07-26 12:06:35 +02:00
Mark Paluch 2632b69d12 DATAES-452 - Prepare 3.1 RC1 (Lovelace). 2018-07-26 12:04:30 +02:00
Mark Paluch d30328f2e1 DATAES-452 - Updated changelog. 2018-07-26 12:04:28 +02:00
Oliver Gierke 469455383f DATAES-470 - Fixed parsing of cluster nodes in TransportClientFactoryBean.
Extracted ClusterNodes value object to capture the parsing logic and actually properly test it. Added unit tests to verify the proper rejection and the two cases outlined in the ticket.

Related tickets: DATAES-283.
2018-07-12 21:48:31 +02:00
Oliver Gierke cdbc832068 DATAES-471 - Adapt object property access behavior after changes in Spring Data Commons.
Changes made for Spring Data Commons result in final fields being rejected for manipulation unless there's a wither method available on the object at hand. Unfortunately adapting Spring Data Elasticsearch to support that doesn't work easily as it requires breaking changes to ElasticsearchTemplate as most of the methods assume parameters being handed to be mutable, see the implementation of SimpleElasticsearchRepository.save(…) for instance.

We now mitigate the problem, by enforcing the BeanWrapperPropertyAccessor being used and treating all properties as mutable.

Related tickets: DATACMNS-1322.
2018-07-12 15:27:36 +02:00
xhaggi 143a359eca DATAES-317 - Introduce query logging in ElasticsearchTemplate.
Original pull request: #180.
2018-06-28 11:21:43 +02:00
xhaggi e58c43f391 DATAES-469 - Remove superfluous dependency elasticsearch. 2018-06-28 11:16:33 +02:00
petar.tahchiev d66b2a6f63 DATAES-283 - Get rid of Commons Lang dependency.
Replace all StringUtils and ArrayUtils usages with Springframework's StringUtils and ObjectUtils. Left the commons-lang as test-scope dependency as I believe it brings some values in the tests.

Original pull request: #211.
2018-06-20 20:10:21 +02:00
xhaggi ba3eba5734 DATAES-467 - Fix sorting by _score if Spring Data sort is used.
Original pull request: #209.
2018-06-18 11:18:31 +02:00
Mark Paluch 4a26af38c3 DATAES-448 - Updated changelog. 2018-06-13 21:39:54 +02:00
Oliver Gierke 5ddb46c435 DATAES-462 - Polishing.
SimpleElasticsearchPersistentProperty now already checks for the correct type of score properties. Added unit tests for that. Also added unit tests for SimpleElasticsearchPersistentEntity rejecting more than one score property being present.

Additional non-null assertions on components that are required so that we can remove superfluous null checks.

A bit o formatting, Javadoc, missing @since tags and license headers.

Original pull request: #207.
2018-06-13 19:00:36 +02:00
xhaggi d996406113 DATAES-462 - Add support for mapping max score and document scores.
Original pull request: #207.
2018-06-13 18:58:13 +02:00
xhaggi 112600261d DATAES-462 - Add query builder option to track scores.
Original pull request: #207.
2018-06-13 18:57:54 +02:00
Oliver Gierke 62a03a8fb7 DATAES-464 - DefaultEntityWriter now considers read-only and transient properties.
We now register a custom Jackson module that filters read-only and transient properties for serialization.
2018-06-13 18:21:37 +02:00
Mark Paluch ac62aaf856 DATAES-447 - Updated changelog. 2018-06-13 15:01:59 +02:00
Christoph Strobl 28629a6ede DATAES-440 - After release cleanups. 2018-05-17 10:09:36 +02:00
Christoph Strobl 12cc5ced16 DATAES-440 - Prepare next development iteration. 2018-05-17 10:09:34 +02:00
Christoph Strobl a807a3801c DATAES-440 - Release version 3.1 M3 (Lovelace). 2018-05-17 09:51:42 +02:00
Christoph Strobl ac2e5be02b DATAES-440 - Prepare 3.1 M3 (Lovelace). 2018-05-17 09:50:48 +02:00
Christoph Strobl b5b8066e6f DATAES-440 - Updated changelog. 2018-05-17 09:50:46 +02:00
Ted Liang e8e407f93b DATAES-312 - Fix NullHandling.NULLS_LAST in query.sort
Original pull request: #163
2018-05-17 09:31:59 +02:00
Nordine Bittich 1b0006f9f7 DATAES-420 - Analyzer of main field ignored when using @MultiField annotation 2018-05-15 17:16:29 +02:00
Oliver Gierke 36c52a5308 DATAES-451 - Adapt to SpEL extension API changes in Spring Data Commons.
Related tickets: DATACMNS-1260.
2018-05-14 17:23:29 +02:00
Mark Paluch 324ab13ca1 DATAES-437 - Updated changelog. 2018-05-08 15:27:21 +02:00
Mark Paluch c87499b189 DATAES-436 - Updated changelog. 2018-05-08 12:22:52 +02:00
xhaggi 64f259cb8e DATAES-427 - update version overview in README 2018-05-08 11:37:00 +02:00
xhaggi 8c4a669ce5 DATAES-285 - fix broken tests after 4970783ca4 2018-05-08 10:47:22 +02:00
xhaggi ace5a21b05 DATAES-285 - Polishing
* drop superfluous class FieldIndex
* change FieldType text and keyword starting with capital letters

Original commit: 089d7746be
2018-05-07 13:19:37 +02:00
xhaggi 9c235cd53c DATAES-412 - only the last highlight field is added to SearchRequest 2018-05-07 11:39:58 +02:00
Chris White ef1dca31e4 DATAES-198 - Fixed @Version annotation on fields. 2018-04-23 17:33:54 +02:00
Alen Turkovic de1afe8bb0 DATAES-422 - Add support for IndicesOptions in search queries.
See also: DATAES-191..
2018-04-20 14:32:01 +02:00
Oliver Gierke 92c3bbebed DATAES-363 - Polishing.
Original pull request: #183.
2018-04-18 12:36:27 +02:00
Michael Wirth 512e9eacad DATAES-363 - Fixed CrudRepository.existsById(…) implementation.
Properly use Optional.isPresent() over a null check.

Original pull request: #183.
2018-04-18 12:36:10 +02:00
Mark Paluch b8400d8d4d DATAES-427 - After release cleanups. 2018-04-13 15:08:34 +02:00
Mark Paluch c53ecdc41c DATAES-427 - Prepare next development iteration. 2018-04-13 15:08:32 +02:00
Mark Paluch c2aca20505 DATAES-427 - Release version 3.1 M2 (Lovelace). 2018-04-13 14:30:58 +02:00
Mark Paluch e703fbc8bf DATAES-427 - Prepare 3.1 M2 (Lovelace). 2018-04-13 14:30:01 +02:00
Mark Paluch 1b44f051c7 DATAES-427 - Updated changelog. 2018-04-13 14:29:59 +02:00
xhaggi b949daadea DATAES-438 - get rid of deprecation warning because of invalid mapping for @Id 2018-04-13 11:55:17 +01:00
Oliver Gierke 8c40bac9ab DATAES-439 - Adapt to API changes in Spring Data Commons.
Related tickets: DATACMNS-1275.
2018-04-09 14:40:47 +02:00
Mark Paluch 9fba9ea076 DATAES-430 - Updated changelog. 2018-04-04 17:12:55 +02:00
Mark Paluch b5d5fdc32e DATAES-423 - Updated changelog. 2018-04-04 15:16:22 +02:00
Oliver Gierke 6db756a233 DATAES-434 - Removed explicit declaration of Jackson library versions. 2018-03-27 19:38:13 +02:00
Artur Konczak e50e5f9146 DATAES-402 - fixed broken tests 2018-03-15 13:43:06 +00:00
Remco Zigterman 4856974c1a DATAES-402 - fixing paging information 2018-03-15 09:57:19 +00:00
Artur Konczak 51f9485700 DATAES-421 updated to latest version of ES 6.2.2 2018-03-15 09:14:43 +00:00
rivergod e7b93bee90 DATAES-421 - Update ES to 6.1.0 2018-03-15 09:14:43 +00:00
Mark Paluch 9bc9c47f42 DATAES-432 - Export composable repositories via CDI.
We now export composable repositories through our CDI extension. Repositories can now be customized either by a single custom implementation (as it was before) and by providing fragment interfaces along their fragment implementation.

This change aligns CDI support with the existing RepositoryFactory support we provide within a Spring application context.
2018-03-12 17:00:16 +01:00
Mark Paluch 4313d13ddd DATAES-429 - Updated changelog. 2018-02-28 11:17:39 +01:00
Mark Paluch 2075775478 DATAES-425 - Updated changelog. 2018-02-19 20:30:08 +01:00
Christoph Strobl e4009df6b9 DATAES-401 - After release cleanups. 2018-02-06 10:11:17 +01:00
Christoph Strobl 053e1726f5 DATAES-401 - Prepare next development iteration. 2018-02-06 10:11:15 +01:00
Christoph Strobl d2690abbdf DATAES-401 - Release version 3.1 M1 (Lovelace). 2018-02-06 09:47:10 +01:00
Christoph Strobl cf6d299941 DATAES-401 - Prepare 3.1 M1 (Lovelace). 2018-02-06 09:45:50 +01:00
Christoph Strobl 4d0159a560 DATAES-401 - Updated changelog. 2018-02-06 09:45:48 +01:00
Mark Paluch 028bc13eb7 DATAES-417 - Updated changelog. 2018-01-24 13:41:24 +01:00
Mark Paluch 9bfc6f23b9 DATAES-424 - Fix line endings to LF. 2018-01-24 13:06:40 +01:00
Mark Paluch 4bd263a25a DATAES-416 - Updated changelog. 2018-01-24 12:22:14 +01:00
Mark Paluch 00e30fd802 DATAES-411 - Updated changelog. 2017-11-27 16:43:43 +01:00
Mark Paluch 22e10801ca DATAES-404 - Updated changelog. 2017-11-27 15:58:47 +01:00
Oliver Gierke f7d77f05de DATAES-414 - Reduced scope of Log4j dependencies to test. 2017-11-02 18:40:56 +01:00
Oliver Gierke 71ebc3dd21 DATAES-400 - Updated changelog. 2017-10-27 16:36:52 +02:00
Oliver Gierke 51d0f95f65 DATAES-410 - Adapt API changes in Property in test cases. 2017-10-27 11:24:34 +02:00
Vladimir Tsanev 75f34e4d02 DATAES-361 - Move Log4j2 config file to test sources.
The configuration file for Log4j2 had been added to src/main/resources accidentally which caused it to be picked up by user applications, e.g. in a Spring Boot application effectively disabling Boot's auto-configuration. This file has now been moved to the test resources.

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

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

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

Related Ticket: DATAES-350.
2017-04-24 10:33:45 +02:00
Oliver Gierke 05a0186d1e DATAES-347 - Updated changelog. 2017-04-19 21:04:25 +02:00
Oliver Gierke 5182dabd88 DATAES-346 - Updated changelog. 2017-04-19 20:01:50 +02:00
Oliver Gierke 14ee378eea DATAES-336 - Updated changelog. 2017-04-19 13:04:12 +02:00
Oliver Gierke 53b6444c9d DATAES-335 - Updated changelog. 2017-04-19 11:50:51 +02:00
Oliver Gierke e15d894232 DATAES-326 - Updated changelog. 2017-04-10 14:31:44 +02:00
Oliver Gierke 4bb7f894ee DATAES-311 - After release cleanups. 2017-04-04 22:08:19 +02:00
Oliver Gierke 8f0df67532 DATAES-311 - Prepare next development iteration. 2017-04-04 22:08:16 +02:00
Oliver Gierke 1266de6af3 DATAES-311 - Release version 3.0 M2 (Kay). 2017-04-04 21:12:36 +02:00
Oliver Gierke 311b3c3c00 DATAES-311 - Prepare 3.0 M2 (Kay). 2017-04-04 21:12:02 +02:00
Oliver Gierke e897ba3809 DATAES-311 - Updated changelog. 2017-04-04 21:12:00 +02:00
Mark Paluch 7f995b38f9 DATAES-342 - Adapt to API changes in RepositoryConfigurationExtensionSupport. 2017-03-27 08:47:27 +02:00
Oliver Gierke ff18271917 DATAES-328 - Adapt to API cchanges after Mockito 2.7 upgrade. 2017-03-24 09:44:49 +01:00
Mark Paluch 519a2a11a4 DATAES-328 - Adapt to API changes in Spring Data Commons. 2017-03-24 09:44:49 +01:00
Mark Paluch 5f3bacf950 DATAES-328 - Reduce null usage, use PageRequest.of factory method. 2017-03-24 09:44:49 +01:00
Mark Paluch 4c7dd4939a DATAES-328 - Replace explicit generics with diamond operator. 2017-03-24 09:44:49 +01:00
Mark Paluch 0cada7f374 DATAES-328 - Integrate Data Commons Java 8 upgrade branch. 2017-03-24 09:44:49 +01:00
Mark Paluch 64bad236da DATAES-328 - Update pom.xml links to Jira and Bamboo. Remove dist.key. 2017-03-24 09:44:47 +01:00
Oliver Gierke 4cb22f1520 DATAES-327 - Updated changelog. 2017-03-02 11:11:06 +01:00
Mark Paluch 642eabeb9b DATAES-329 - Remove references to Assert single-arg methods.
Replace references to Assert single-arg methods with references to methods accepting the test object and message.

Related ticket: SPR-15196.
2017-02-02 08:41:56 +01:00
Mark Paluch cda69367b7 DATAES-325 - Replace references to GenericCollectionTypeResolver with ResolvableType.
Using ResolvableType instead of GenericCollectionTypeResolver that is removed with Spring 5.

Related ticket: SPR-15160.
2017-01-26 14:01:51 +01:00
Oliver Gierke 6bcf3e0b52 DATAES-319 - Updated changelog. 2017-01-26 12:12:40 +01:00
Oliver Gierke 6bb59fd084 DATAES-320 - Updated changelog. 2017-01-26 12:12:09 +01:00
Mark Paluch de9dc477f0 DATAES-322 - Update project documentation with the CLA tool integration. 2017-01-13 11:31:41 +01:00
Oliver Gierke 6353881de8 DATAES-304 - Updated changelog. 2016-12-21 19:35:42 +01:00
Oliver Gierke 7470652ef9 DATAES-275 - Updated changelog. 2016-12-21 18:43:06 +01:00
Oliver Gierke 9754d70bfa DATAES-315 - Adapt API in ElasticsearchRepositoryFactoryBean.
Related ticket: DATACMNS-891.
2016-12-15 16:22:17 +01:00
Mark Paluch c8c3e0a5ec DATAES-313 - Register ElasticsearchRepositoryFactory in spring.factories.
This is required for the switch in support for multi-store detection.

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

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