Compare commits
157 Commits
1.2.x
...
2.1.1.RELEASE
| Author | SHA1 | Date | |
|---|---|---|---|
| c28f41a2c4 | |||
| 686921c46e | |||
| d1e11ef5f9 | |||
| c0ef590038 | |||
| 692142ea65 | |||
| 6e2331b040 | |||
| 29910fc9ef | |||
| 38604eb64d | |||
| 344f439778 | |||
| ea07d697ad | |||
| 6b549339c8 | |||
| 3c2894e45d | |||
| d921f9d9a3 | |||
| af1f658712 | |||
| 18c30078ba | |||
| 812e202f15 | |||
| bf4cadbdd8 | |||
| 200f1771d5 | |||
| b83a097892 | |||
| 6d08e92117 | |||
| fce9c1fd60 | |||
| ceffbeebd1 | |||
| 42ba51546e | |||
| 8df87b3268 | |||
| bc3c2dc12c | |||
| 5483564f08 | |||
| db3174dbbe | |||
| 896fbbebc8 | |||
| 7a95cb64a8 | |||
| 2718be7c07 | |||
| c7dfd2131e | |||
| 2b60128390 | |||
| 53b587101d | |||
| 063d8ed983 | |||
| e5b080a9b0 | |||
| 7113c7ac66 | |||
| 7e736a6271 | |||
| 20c5d19963 | |||
| b1e9f77a2b | |||
| 7b6979166a | |||
| a3a6f9cc67 | |||
| ecc62cc1b4 | |||
| edfca24527 | |||
| 392a87ab0a | |||
| 6ffac62b3e | |||
| fd06f8efd7 | |||
| 8c77d314aa | |||
| f569b0348a | |||
| 99a401fdff | |||
| 6c0272880a | |||
| 22d81083b4 | |||
| c65a573b23 | |||
| a362361ace | |||
| d9e66aa532 | |||
| 5094482b6c | |||
| b6a8f2f832 | |||
| c856680523 | |||
| ef0831fa33 | |||
| b2f0300856 | |||
| 246da57993 | |||
| 72ca7477fc | |||
| 3a41435155 | |||
| cbb3a7afc4 | |||
| 800b10b2b1 | |||
| 023214a344 | |||
| 477e8e2a07 | |||
| 374acbdd63 | |||
| 8bb4ac3653 | |||
| 907571e550 | |||
| f98d888151 | |||
| a8d915f830 | |||
| f493db7774 | |||
| c4b4a8c45d | |||
| 1cf18a4a50 | |||
| 6535caff8a | |||
| 2aa7ed1c23 | |||
| 0f6004ae94 | |||
| e9576adb1a | |||
| ca7a7fb382 | |||
| c5c9956bc0 | |||
| 4930415302 | |||
| 42fc41b2eb | |||
| 4e0cbb8966 | |||
| 95194961dc | |||
| 6a2b5fd945 | |||
| 4efec54e1d | |||
| c7313b52eb | |||
| a05a597123 | |||
| 61880671a4 | |||
| 09455006ab | |||
| 924467ec94 | |||
| 8963123ffe | |||
| a853ca359a | |||
| 76d8d5fe3e | |||
| de821410f2 | |||
| ba8bd886d4 | |||
| fd4b74313f | |||
| fad5162b26 | |||
| d5cdba06b3 | |||
| 4296760eb0 | |||
| 403a85b094 | |||
| 428cac3642 | |||
| ba1fb9fc6f | |||
| 9c91723833 | |||
| 7dbab75cf5 | |||
| d6603f8edf | |||
| 727cb5eb09 | |||
| aa44da63f9 | |||
| 23e1e9f46a | |||
| 751302d6f0 | |||
| 485f0e7252 | |||
| aa9c47516c | |||
| 21ff7e50cf | |||
| 909caa732b | |||
| 5b850c61e2 | |||
| 9981ad0dba | |||
| bcc763b97b | |||
| 131b172ce2 | |||
| 7d645ac5e1 | |||
| 4350234299 | |||
| 5a648bcb7a | |||
| 6a06bbfbb9 | |||
| c2f13c3820 | |||
| 49708d38c0 | |||
| d9212630b9 | |||
| 9682e7ee28 | |||
| a6d4109d0b | |||
| 6a6c44401d | |||
| 7f4ee37be3 | |||
| bc8b5b8bd8 | |||
| 6cdc765b24 | |||
| f9e0b3a4f9 | |||
| 52fec26a1d | |||
| eadf51ec27 | |||
| af3121a165 | |||
| 9b28ca805b | |||
| 9d8bc61401 | |||
| ae1a873705 | |||
| 9524b2cc8d | |||
| d83a6541aa | |||
| fdc62dd7d6 | |||
| 416daef2f9 | |||
| 576495932e | |||
| c9ffc4417a | |||
| e80ddd249f | |||
| 9a8c04c16f | |||
| d117f6f515 | |||
| 3e1099740b | |||
| 763e61c862 | |||
| ea02e99263 | |||
| a3828c6161 | |||
| 4a90020dc1 | |||
| 01a67eef05 | |||
| 0825f15ec3 | |||
| 7aaf7e1782 | |||
| 455df72923 | |||
| cee493a6c7 |
@@ -0,0 +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. Don’t 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).
|
||||
@@ -0,0 +1,27 @@
|
||||
= Contributor Code of Conduct
|
||||
|
||||
As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
||||
|
||||
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery
|
||||
* Personal attacks
|
||||
* Trolling or insulting/derogatory comments
|
||||
* Public or private harassment
|
||||
* Publishing other's private information, such as physical or electronic addresses,
|
||||
without explicit permission
|
||||
* Other unethical or unprofessional conduct
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a project maintainer at spring-code-of-conduct@pivotal.io.
|
||||
All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances.
|
||||
Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
|
||||
This Code of Conduct is adapted from the http://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at http://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/].
|
||||
@@ -0,0 +1,3 @@
|
||||
= Spring Data contribution guidelines
|
||||
|
||||
You find the contribution guidelines for Spring Data projects https://github.com/spring-projects/spring-data-build/blob/master/CONTRIBUTING.adoc[here].
|
||||
@@ -11,12 +11,12 @@ Guide
|
||||
------------
|
||||
|
||||
* [Reference Documentation](http://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/)
|
||||
* [PDF Documentation](http://docs.spring.io/spring-data/elasticsearch/docs/current/reference/pdf/spring-data-elasticsearch-reference.pdf)
|
||||
* [API Documentation](http://docs.spring.io/spring-data/elasticsearch/docs/current/api/)
|
||||
* [Spring Data Project](http://projects.spring.io/spring-data)
|
||||
* [Sample Test Application](https://github.com/BioMedCentralLtd/spring-data-elasticsearch-sample-application)
|
||||
* [Issues](https://jira.springsource.org/browse/DATAES)
|
||||
* [Spring Data Elasticsearch Google Group](https://groups.google.com/d/forum/spring-data-elasticsearch-devs)
|
||||
* For more detailed questions, use the [forum](http://forum.springsource.org/forumdisplay.php?f=80).
|
||||
* [Questions](http://stackoverflow.com/questions/tagged/spring-data-elasticsearch)
|
||||
|
||||
|
||||
Quick Start
|
||||
@@ -31,7 +31,7 @@ Add the Maven dependency:
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-elasticsearch</artifactId>
|
||||
<version>1.2.0.RELEASE</version>
|
||||
<version>2.0.4.RELEASE</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
@@ -42,7 +42,7 @@ the appropriate dependency version.
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-elasticsearch</artifactId>
|
||||
<version>1.3.0.BUILD-SNAPSHOT</version>
|
||||
<version>2.1.0.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<repository>
|
||||
@@ -52,10 +52,16 @@ the appropriate dependency version.
|
||||
</repository>
|
||||
```
|
||||
|
||||
###Note:
|
||||
Spring data elaticsearch until 1.0.0.RELEASE version is on elasticsearch 1.1.x library, which uses java 1.6 or later version.
|
||||
| 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 |
|
||||
|
||||
From spring data elastic search 1.1.0.RELEASE (current) on, the version of elasticsearch 1.3.x is supporting java 1.7 or later.
|
||||
|
||||
### ElasticsearchRepository
|
||||
A default implementation of ElasticsearchRepository, aligning to the generic Repository Interfaces, is provided. Spring can do the Repository implementation for you depending on method names in the interface definition.
|
||||
@@ -239,9 +245,9 @@ Here are some ways for you to get involved in the community:
|
||||
* 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 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. 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)
|
||||
|
||||
[More information about contributing to Spring Data](https://github.com/spring-projects/spring-data-build/blob/master/CONTRIBUTING.md)
|
||||
[More information about contributing to Spring Data](https://github.com/spring-projects/spring-data-build/blob/master/CONTRIBUTING.adoc)
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-elasticsearch</artifactId>
|
||||
<version>1.3.0.BUILD-SNAPSHOT</version>
|
||||
<version>2.1.1.RELEASE</version>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data.build</groupId>
|
||||
<artifactId>spring-data-parent</artifactId>
|
||||
<version>1.7.0.BUILD-SNAPSHOT</version>
|
||||
<version>1.9.1.RELEASE</version>
|
||||
<relativePath>../spring-data-build/parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
|
||||
<commonscollections>3.2.1</commonscollections>
|
||||
<commonslang>2.6</commonslang>
|
||||
<elasticsearch>1.4.4</elasticsearch>
|
||||
<springdata.commons>1.11.0.BUILD-SNAPSHOT</springdata.commons>
|
||||
<elasticsearch>2.4.0</elasticsearch>
|
||||
<springdata.commons>1.13.1.RELEASE</springdata.commons>
|
||||
|
||||
</properties>
|
||||
|
||||
@@ -60,11 +60,6 @@
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<version>${commonslang}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-collections</groupId>
|
||||
<artifactId>commons-collections</artifactId>
|
||||
<version>${commonscollections}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JODA Time -->
|
||||
<dependency>
|
||||
@@ -91,7 +86,7 @@
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- CDI -->
|
||||
<dependency>
|
||||
<groupId>javax.enterprise</groupId>
|
||||
@@ -105,7 +100,6 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${spring}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -113,6 +107,16 @@
|
||||
<artifactId>cditest-owb</artifactId>
|
||||
<version>${webbeans}</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.geronimo.specs</groupId>
|
||||
<artifactId>geronimo-jcdi_1.0_spec</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.apache.geronimo.specs</groupId>
|
||||
<artifactId>geronimo-atinject_1.0_spec</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
@@ -121,6 +125,13 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -140,6 +151,21 @@
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>release</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jfrog.buildinfo</groupId>
|
||||
<artifactId>artifactory-maven-plugin</artifactId>
|
||||
<inherited>false</inherited>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>biomedcentral</id>
|
||||
@@ -150,8 +176,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>
|
||||
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ public @interface CompletionField {
|
||||
|
||||
String searchAnalyzer() default "simple";
|
||||
|
||||
String indexAnalyzer() default "simple";
|
||||
String analyzer() default "simple";
|
||||
|
||||
boolean payloads() default false;
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.springframework.data.annotation.Persistent;
|
||||
*
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Mason Chan
|
||||
*/
|
||||
|
||||
@Persistent
|
||||
@@ -36,6 +37,8 @@ public @interface Document {
|
||||
|
||||
String type() default "";
|
||||
|
||||
boolean useServerConfiguration() default false;
|
||||
|
||||
short shards() default 5;
|
||||
|
||||
short replicas() default 1;
|
||||
@@ -43,4 +46,6 @@ public @interface Document {
|
||||
String refreshInterval() default "1s";
|
||||
|
||||
String indexStoreType() default "fs";
|
||||
|
||||
boolean createIndex() default true;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public @interface Field {
|
||||
|
||||
String searchAnalyzer() default "";
|
||||
|
||||
String indexAnalyzer() default "";
|
||||
String analyzer() default "";
|
||||
|
||||
String[] ignoreFields() default {};
|
||||
|
||||
|
||||
@@ -21,5 +21,5 @@ package org.springframework.data.elasticsearch.annotations;
|
||||
* @author Artur Konczak
|
||||
*/
|
||||
public enum FieldType {
|
||||
String, Integer, Long, Date, Float, Double, Boolean, Object, Auto, Nested, Ip
|
||||
String, Integer, Long, Date, Float, Double, Boolean, Object, Auto, Nested, Ip, Attachment
|
||||
}
|
||||
|
||||
@@ -25,4 +25,8 @@ import java.lang.annotation.*;
|
||||
@Documented
|
||||
public @interface GeoPointField {
|
||||
|
||||
boolean geoHashPrefix() default false;
|
||||
|
||||
String geoHashPrecision() default "0";
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -25,9 +25,9 @@ import java.lang.annotation.Target;
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface NestedField {
|
||||
public @interface InnerField {
|
||||
|
||||
String dotSuffix();
|
||||
String suffix();
|
||||
|
||||
FieldType type();
|
||||
|
||||
@@ -26,7 +26,7 @@ import org.springframework.data.annotation.Persistent;
|
||||
@Persistent
|
||||
@Inherited
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
@Target({ElementType.TYPE, ElementType.FIELD})
|
||||
public @interface Mapping {
|
||||
|
||||
String mappingPath() default "";
|
||||
|
||||
@@ -30,5 +30,5 @@ public @interface MultiField {
|
||||
|
||||
public Field mainField();
|
||||
|
||||
public NestedField[] otherFields() default {};
|
||||
public InnerField[] otherFields() default {};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.springframework.data.elasticsearch.annotations;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @author Ryan Murfitt
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
@Documented
|
||||
public @interface ScriptedField {
|
||||
|
||||
/**
|
||||
* (Optional) The name of the scripted field. Defaults to
|
||||
* the field name.
|
||||
*/
|
||||
String name() default "";
|
||||
|
||||
}
|
||||
+35
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,9 +17,11 @@ package org.springframework.data.elasticsearch.client;
|
||||
|
||||
import static org.elasticsearch.node.NodeBuilder.*;
|
||||
|
||||
import java.io.InputStream;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.client.node.NodeClient;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
@@ -40,6 +42,9 @@ public class NodeClientFactoryBean implements FactoryBean<NodeClient>, Initializ
|
||||
private boolean enableHttp;
|
||||
private String clusterName;
|
||||
private NodeClient nodeClient;
|
||||
private String pathData;
|
||||
private String pathHome;
|
||||
private String pathConfiguration;
|
||||
|
||||
NodeClientFactoryBean() {
|
||||
}
|
||||
@@ -65,13 +70,25 @@ public class NodeClientFactoryBean implements FactoryBean<NodeClient>, Initializ
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
ImmutableSettings.Builder settings = ImmutableSettings.settingsBuilder().put("http.enabled",
|
||||
String.valueOf(this.enableHttp));
|
||||
|
||||
nodeClient = (NodeClient) nodeBuilder().settings(settings).clusterName(this.clusterName).local(this.local).node()
|
||||
nodeClient = (NodeClient) nodeBuilder().settings(Settings.builder().put(loadConfig())
|
||||
.put("http.enabled", String.valueOf(this.enableHttp))
|
||||
.put("path.home", this.pathHome)
|
||||
.put("path.data", this.pathData))
|
||||
.clusterName(this.clusterName).local(this.local).node()
|
||||
.client();
|
||||
}
|
||||
|
||||
private Settings loadConfig() {
|
||||
if (StringUtils.isNotBlank(pathConfiguration)) {
|
||||
InputStream stream = getClass().getClassLoader().getResourceAsStream(pathConfiguration);
|
||||
if (stream != null) {
|
||||
return Settings.builder().loadFromStream(pathConfiguration, getClass().getClassLoader().getResourceAsStream(pathConfiguration)).build();
|
||||
}
|
||||
logger.error(String.format("Unable to read node configuration from file [%s]", pathConfiguration));
|
||||
}
|
||||
return Settings.builder().build();
|
||||
}
|
||||
|
||||
public void setLocal(boolean local) {
|
||||
this.local = local;
|
||||
}
|
||||
@@ -84,6 +101,18 @@ public class NodeClientFactoryBean implements FactoryBean<NodeClient>, Initializ
|
||||
this.clusterName = clusterName;
|
||||
}
|
||||
|
||||
public void setPathData(String pathData) {
|
||||
this.pathData = pathData;
|
||||
}
|
||||
|
||||
public void setPathHome(String pathHome) {
|
||||
this.pathHome = pathHome;
|
||||
}
|
||||
|
||||
public void setPathConfiguration(String configuration) {
|
||||
this.pathConfiguration = configuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
try {
|
||||
|
||||
+7
-7
@@ -16,8 +16,8 @@
|
||||
package org.springframework.data.elasticsearch.client;
|
||||
|
||||
import static org.apache.commons.lang.StringUtils.*;
|
||||
import static org.elasticsearch.common.settings.ImmutableSettings.*;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.elasticsearch.client.transport.TransportClient;
|
||||
@@ -86,24 +86,24 @@ public class TransportClientFactoryBean implements FactoryBean<TransportClient>,
|
||||
}
|
||||
|
||||
protected void buildClient() throws Exception {
|
||||
client = new TransportClient(settings());
|
||||
client = TransportClient.builder().settings(settings()).build();
|
||||
Assert.hasText(clusterNodes, "[Assertion failed] clusterNodes settings missing.");
|
||||
for (String clusterNode : split(clusterNodes, COMMA)) {
|
||||
String hostName = substringBefore(clusterNode, COLON);
|
||||
String port = substringAfter(clusterNode, COLON);
|
||||
String hostName = substringBeforeLast(clusterNode, COLON);
|
||||
String port = substringAfterLast(clusterNode, COLON);
|
||||
Assert.hasText(hostName, "[Assertion failed] missing host name in 'clusterNodes'");
|
||||
Assert.hasText(port, "[Assertion failed] missing port in 'clusterNodes'");
|
||||
logger.info("adding transport node : " + clusterNode);
|
||||
client.addTransportAddress(new InetSocketTransportAddress(hostName, Integer.valueOf(port)));
|
||||
client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(hostName), Integer.valueOf(port)));
|
||||
}
|
||||
client.connectedNodes();
|
||||
}
|
||||
|
||||
private Settings settings() {
|
||||
if (properties != null) {
|
||||
return settingsBuilder().put(properties).build();
|
||||
return Settings.builder().put(properties).build();
|
||||
}
|
||||
return settingsBuilder()
|
||||
return Settings.builder()
|
||||
.put("cluster.name", clusterName)
|
||||
.put("client.transport.sniff", clientTransportSniff)
|
||||
.put("client.transport.ignore_cluster_name", clientIgnoreClusterName)
|
||||
|
||||
+4
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -43,6 +43,9 @@ public class NodeClientBeanDefinitionParser extends AbstractBeanDefinitionParser
|
||||
builder.addPropertyValue("local", Boolean.valueOf(element.getAttribute("local")));
|
||||
builder.addPropertyValue("clusterName", element.getAttribute("cluster-name"));
|
||||
builder.addPropertyValue("enableHttp", Boolean.valueOf(element.getAttribute("http-enabled")));
|
||||
builder.addPropertyValue("pathData", element.getAttribute("path-data"));
|
||||
builder.addPropertyValue("pathHome", element.getAttribute("path-home"));
|
||||
builder.addPropertyValue("pathConfiguration", element.getAttribute("path-configuration"));
|
||||
}
|
||||
|
||||
private AbstractBeanDefinition getSourcedBeanDefinition(BeanDefinitionBuilder builder, Element source,
|
||||
|
||||
+38
-31
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import static org.elasticsearch.index.query.FilterBuilders.*;
|
||||
import static org.springframework.data.elasticsearch.core.query.Criteria.*;
|
||||
|
||||
import java.util.Iterator;
|
||||
@@ -23,9 +22,8 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import org.elasticsearch.index.query.FilterBuilder;
|
||||
import org.elasticsearch.index.query.GeoBoundingBoxFilterBuilder;
|
||||
import org.elasticsearch.index.query.GeoDistanceFilterBuilder;
|
||||
import org.elasticsearch.common.geo.GeoDistance;
|
||||
import org.elasticsearch.index.query.*;
|
||||
import org.springframework.data.elasticsearch.core.geo.GeoBox;
|
||||
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
||||
import org.springframework.data.elasticsearch.core.query.Criteria;
|
||||
@@ -39,24 +37,30 @@ import org.springframework.util.Assert;
|
||||
* CriteriaFilterProcessor
|
||||
*
|
||||
* @author Franck Marchand
|
||||
* @author Mohsin Husen
|
||||
* @author Artur Konczak
|
||||
*
|
||||
*/
|
||||
class CriteriaFilterProcessor {
|
||||
|
||||
|
||||
FilterBuilder createFilterFromCriteria(Criteria criteria) {
|
||||
List<FilterBuilder> fbList = new LinkedList<FilterBuilder>();
|
||||
FilterBuilder filter = null;
|
||||
QueryBuilder createFilterFromCriteria(Criteria criteria) {
|
||||
List<QueryBuilder> fbList = new LinkedList<QueryBuilder>();
|
||||
QueryBuilder filter = null;
|
||||
|
||||
ListIterator<Criteria> chainIterator = criteria.getCriteriaChain().listIterator();
|
||||
|
||||
while (chainIterator.hasNext()) {
|
||||
FilterBuilder fb = null;
|
||||
QueryBuilder fb = null;
|
||||
Criteria chainedCriteria = chainIterator.next();
|
||||
if (chainedCriteria.isOr()) {
|
||||
fb = orFilter(createFilterFragmentForCriteria(chainedCriteria).toArray(new FilterBuilder[]{}));
|
||||
fb = QueryBuilders.boolQuery();
|
||||
for(QueryBuilder f: createFilterFragmentForCriteria(chainedCriteria)){
|
||||
((BoolQueryBuilder)fb).should(f);
|
||||
}
|
||||
fbList.add(fb);
|
||||
} else if (chainedCriteria.isNegating()) {
|
||||
List<FilterBuilder> negationFilters = buildNegationFilter(criteria.getField().getName(), criteria.getFilterCriteriaEntries().iterator());
|
||||
List<QueryBuilder> negationFilters = buildNegationFilter(criteria.getField().getName(), criteria.getFilterCriteriaEntries().iterator());
|
||||
|
||||
if (!negationFilters.isEmpty()) {
|
||||
fbList.addAll(negationFilters);
|
||||
@@ -70,21 +74,23 @@ class CriteriaFilterProcessor {
|
||||
if (fbList.size() == 1) {
|
||||
filter = fbList.get(0);
|
||||
} else {
|
||||
filter = andFilter(fbList.toArray(new FilterBuilder[]{}));
|
||||
filter = QueryBuilders.boolQuery();
|
||||
for(QueryBuilder f: fbList) {
|
||||
((BoolQueryBuilder)filter).must(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
|
||||
private List<FilterBuilder> createFilterFragmentForCriteria(Criteria chainedCriteria) {
|
||||
private List<QueryBuilder> createFilterFragmentForCriteria(Criteria chainedCriteria) {
|
||||
Iterator<Criteria.CriteriaEntry> it = chainedCriteria.getFilterCriteriaEntries().iterator();
|
||||
List<FilterBuilder> filterList = new LinkedList<FilterBuilder>();
|
||||
List<QueryBuilder> filterList = new LinkedList<QueryBuilder>();
|
||||
|
||||
String fieldName = chainedCriteria.getField().getName();
|
||||
Assert.notNull(fieldName, "Unknown field");
|
||||
FilterBuilder filter = null;
|
||||
QueryBuilder filter = null;
|
||||
|
||||
while (it.hasNext()) {
|
||||
Criteria.CriteriaEntry entry = it.next();
|
||||
@@ -96,15 +102,15 @@ class CriteriaFilterProcessor {
|
||||
}
|
||||
|
||||
|
||||
private FilterBuilder processCriteriaEntry(OperationKey key, Object value, String fieldName) {
|
||||
private QueryBuilder processCriteriaEntry(OperationKey key, Object value, String fieldName) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
FilterBuilder filter = null;
|
||||
QueryBuilder filter = null;
|
||||
|
||||
switch (key) {
|
||||
case WITHIN: {
|
||||
filter = geoDistanceFilter(fieldName);
|
||||
GeoDistanceQueryBuilder geoDistanceQueryBuilder = QueryBuilders.geoDistanceQuery(fieldName);
|
||||
|
||||
Assert.isTrue(value instanceof Object[], "Value of a geo distance filter should be an array of two values.");
|
||||
Object[] valArray = (Object[]) value;
|
||||
@@ -123,25 +129,26 @@ class CriteriaFilterProcessor {
|
||||
|
||||
if (valArray[0] instanceof GeoPoint) {
|
||||
GeoPoint loc = (GeoPoint) valArray[0];
|
||||
((GeoDistanceFilterBuilder) filter).lat(loc.getLat()).lon(loc.getLon()).distance(dist.toString());
|
||||
geoDistanceQueryBuilder.lat(loc.getLat()).lon(loc.getLon()).distance(dist.toString()).geoDistance(GeoDistance.PLANE);
|
||||
} else if (valArray[0] instanceof Point) {
|
||||
GeoPoint loc = GeoPoint.fromPoint((Point) valArray[0]);
|
||||
((GeoDistanceFilterBuilder) filter).lat(loc.getLat()).lon(loc.getLon()).distance(dist.toString());
|
||||
geoDistanceQueryBuilder.lat(loc.getLat()).lon(loc.getLon()).distance(dist.toString()).geoDistance(GeoDistance.PLANE);
|
||||
} else {
|
||||
String loc = (String) valArray[0];
|
||||
if (loc.contains(",")) {
|
||||
String c[] = loc.split(",");
|
||||
((GeoDistanceFilterBuilder) filter).lat(Double.parseDouble(c[0])).lon(Double.parseDouble(c[1])).distance(dist.toString());
|
||||
geoDistanceQueryBuilder.lat(Double.parseDouble(c[0])).lon(Double.parseDouble(c[1])).distance(dist.toString()).geoDistance(GeoDistance.PLANE);
|
||||
} else {
|
||||
((GeoDistanceFilterBuilder) filter).geohash(loc).distance(dist.toString());
|
||||
geoDistanceQueryBuilder.geohash(loc).distance(dist.toString()).geoDistance(GeoDistance.PLANE);
|
||||
}
|
||||
}
|
||||
filter = geoDistanceQueryBuilder;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BBOX: {
|
||||
filter = geoBoundingBoxFilter(fieldName);
|
||||
filter = QueryBuilders.geoBoundingBoxQuery(fieldName);
|
||||
|
||||
Assert.isTrue(value instanceof Object[], "Value of a boundedBy filter should be an array of one or two values.");
|
||||
Object[] valArray = (Object[]) value;
|
||||
@@ -149,11 +156,11 @@ class CriteriaFilterProcessor {
|
||||
|
||||
if (valArray.length == 1) {
|
||||
//GeoEnvelop
|
||||
oneParameterBBox((GeoBoundingBoxFilterBuilder) filter, valArray[0]);
|
||||
oneParameterBBox((GeoBoundingBoxQueryBuilder) filter, valArray[0]);
|
||||
} else if (valArray.length == 2) {
|
||||
//2x GeoPoint
|
||||
//2x String
|
||||
twoParameterBBox((GeoBoundingBoxFilterBuilder) filter, valArray);
|
||||
twoParameterBBox((GeoBoundingBoxQueryBuilder) filter, valArray);
|
||||
} else {
|
||||
//error
|
||||
Assert.isTrue(false, "Geo distance filter takes a 1-elements array(GeoBox) or 2-elements array(GeoPoints or Strings(format lat,lon or geohash)).");
|
||||
@@ -188,7 +195,7 @@ class CriteriaFilterProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
private void oneParameterBBox(GeoBoundingBoxFilterBuilder filter, Object value) {
|
||||
private void oneParameterBBox(GeoBoundingBoxQueryBuilder filter, Object value) {
|
||||
Assert.isTrue(value instanceof GeoBox || value instanceof Box, "single-element of boundedBy filter must be type of GeoBox or Box");
|
||||
|
||||
GeoBox geoBBox;
|
||||
@@ -212,7 +219,7 @@ class CriteriaFilterProcessor {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void twoParameterBBox(GeoBoundingBoxFilterBuilder filter, Object[] values) {
|
||||
private void twoParameterBBox(GeoBoundingBoxQueryBuilder filter, Object[] values) {
|
||||
Assert.isTrue(isType(values, GeoPoint.class) || isType(values, String.class), " both elements of boundedBy filter must be type of GeoPoint or String(format lat,lon or geohash)");
|
||||
if (values[0] instanceof GeoPoint) {
|
||||
GeoPoint topLeft = (GeoPoint) values[0];
|
||||
@@ -227,12 +234,12 @@ class CriteriaFilterProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
private List<FilterBuilder> buildNegationFilter(String fieldName, Iterator<Criteria.CriteriaEntry> it) {
|
||||
List<FilterBuilder> notFilterList = new LinkedList<FilterBuilder>();
|
||||
private List<QueryBuilder> buildNegationFilter(String fieldName, Iterator<Criteria.CriteriaEntry> it) {
|
||||
List<QueryBuilder> notFilterList = new LinkedList<QueryBuilder>();
|
||||
|
||||
while (it.hasNext()) {
|
||||
Criteria.CriteriaEntry criteriaEntry = it.next();
|
||||
FilterBuilder notFilter = notFilter(processCriteriaEntry(criteriaEntry.getKey(), criteriaEntry.getValue(), fieldName));
|
||||
QueryBuilder notFilter = QueryBuilders.boolQuery().mustNot(processCriteriaEntry(criteriaEntry.getKey(), criteriaEntry.getValue(), fieldName));
|
||||
notFilterList.add(notFilter);
|
||||
}
|
||||
|
||||
|
||||
+60
-16
@@ -24,10 +24,11 @@ import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import org.apache.lucene.queryparser.flexible.core.util.StringUtils;
|
||||
import org.elasticsearch.index.query.*;
|
||||
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
||||
import org.elasticsearch.index.query.BoolQueryBuilder;
|
||||
import org.elasticsearch.index.query.BoostableQueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryStringQueryBuilder;
|
||||
import org.springframework.data.elasticsearch.core.query.Criteria;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -36,6 +37,7 @@ import org.springframework.util.Assert;
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Franck Marchand
|
||||
* @author Artur Konczak
|
||||
*/
|
||||
class CriteriaQueryProcessor {
|
||||
|
||||
@@ -49,11 +51,19 @@ class CriteriaQueryProcessor {
|
||||
List<QueryBuilder> mustQueryBuilderList = new LinkedList<QueryBuilder>();
|
||||
|
||||
ListIterator<Criteria> chainIterator = criteria.getCriteriaChain().listIterator();
|
||||
|
||||
QueryBuilder firstQuery = null;
|
||||
boolean negateFirstQuery = false;
|
||||
|
||||
while (chainIterator.hasNext()) {
|
||||
Criteria chainedCriteria = chainIterator.next();
|
||||
QueryBuilder queryFragmentForCriteria = createQueryFragmentForCriteria(chainedCriteria);
|
||||
|
||||
if (queryFragmentForCriteria != null) {
|
||||
if (firstQuery == null) {
|
||||
firstQuery = queryFragmentForCriteria;
|
||||
negateFirstQuery = chainedCriteria.isNegating();
|
||||
continue;
|
||||
}
|
||||
if (chainedCriteria.isOr()) {
|
||||
shouldQueryBuilderList.add(queryFragmentForCriteria);
|
||||
} else if (chainedCriteria.isNegating()) {
|
||||
@@ -64,6 +74,18 @@ class CriteriaQueryProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
if (firstQuery != null) {
|
||||
if (!shouldQueryBuilderList.isEmpty() && mustNotQueryBuilderList.isEmpty() && mustQueryBuilderList.isEmpty()) {
|
||||
shouldQueryBuilderList.add(0, firstQuery);
|
||||
} else {
|
||||
if (negateFirstQuery) {
|
||||
mustNotQueryBuilderList.add(0, firstQuery);
|
||||
} else {
|
||||
mustQueryBuilderList.add(0, firstQuery);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BoolQueryBuilder query = null;
|
||||
|
||||
if (!shouldQueryBuilderList.isEmpty() || !mustNotQueryBuilderList.isEmpty() || !mustQueryBuilderList.isEmpty()) {
|
||||
@@ -98,12 +120,12 @@ class CriteriaQueryProcessor {
|
||||
|
||||
if (singeEntryCriteria) {
|
||||
Criteria.CriteriaEntry entry = it.next();
|
||||
query = processCriteriaEntry(entry.getKey(), entry.getValue(), fieldName);
|
||||
query = processCriteriaEntry(entry, fieldName);
|
||||
} else {
|
||||
query = boolQuery();
|
||||
while (it.hasNext()) {
|
||||
Criteria.CriteriaEntry entry = it.next();
|
||||
((BoolQueryBuilder) query).must(processCriteriaEntry(entry.getKey(), entry.getValue(), fieldName));
|
||||
((BoolQueryBuilder) query).must(processCriteriaEntry(entry, fieldName));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,46 +134,68 @@ class CriteriaQueryProcessor {
|
||||
}
|
||||
|
||||
|
||||
private QueryBuilder processCriteriaEntry(OperationKey key, Object value, String fieldName) {
|
||||
private QueryBuilder processCriteriaEntry(Criteria.CriteriaEntry entry,/* OperationKey key, Object value,*/ String fieldName) {
|
||||
Object value = entry.getValue();
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
OperationKey key = entry.getKey();
|
||||
QueryBuilder query = null;
|
||||
|
||||
String searchText = StringUtils.toString(value);
|
||||
|
||||
Iterable<Object> collection = null;
|
||||
|
||||
switch (key) {
|
||||
case EQUALS:
|
||||
query = queryString(searchText).field(fieldName);
|
||||
query = queryStringQuery(searchText).field(fieldName).defaultOperator(QueryStringQueryBuilder.Operator.AND);
|
||||
break;
|
||||
case CONTAINS:
|
||||
query = queryString("*" + searchText + "*").field(fieldName).analyzeWildcard(true);
|
||||
query = queryStringQuery("*" + searchText + "*").field(fieldName).analyzeWildcard(true);
|
||||
break;
|
||||
case STARTS_WITH:
|
||||
query = queryString(searchText + "*").field(fieldName).analyzeWildcard(true);
|
||||
query = queryStringQuery(searchText + "*").field(fieldName).analyzeWildcard(true);
|
||||
break;
|
||||
case ENDS_WITH:
|
||||
query = queryString("*" + searchText).field(fieldName).analyzeWildcard(true);
|
||||
query = queryStringQuery("*" + searchText).field(fieldName).analyzeWildcard(true);
|
||||
break;
|
||||
case EXPRESSION:
|
||||
query = queryString((String) value).field(fieldName);
|
||||
query = queryStringQuery(searchText).field(fieldName);
|
||||
break;
|
||||
case LESS_EQUAL:
|
||||
query = rangeQuery(fieldName).lte(value);
|
||||
break;
|
||||
case GREATER_EQUAL:
|
||||
query = rangeQuery(fieldName).gte(value);
|
||||
break;
|
||||
case BETWEEN:
|
||||
Object[] ranges = (Object[]) value;
|
||||
query = rangeQuery(fieldName).from(ranges[0]).to(ranges[1]);
|
||||
break;
|
||||
case LESS:
|
||||
query = rangeQuery(fieldName).lt(value);
|
||||
break;
|
||||
case GREATER:
|
||||
query = rangeQuery(fieldName).gt(value);
|
||||
break;
|
||||
case FUZZY:
|
||||
query = fuzzyQuery(fieldName, (String) value);
|
||||
query = fuzzyQuery(fieldName, searchText);
|
||||
break;
|
||||
case IN:
|
||||
query = boolQuery();
|
||||
Iterable<Object> collection = (Iterable<Object>) value;
|
||||
collection = (Iterable<Object>) value;
|
||||
for (Object item : collection) {
|
||||
((BoolQueryBuilder) query).should(queryString((String) item).field(fieldName));
|
||||
((BoolQueryBuilder) query).should(queryStringQuery(item.toString()).field(fieldName));
|
||||
}
|
||||
break;
|
||||
case NOT_IN:
|
||||
query = boolQuery();
|
||||
collection = (Iterable<Object>) value;
|
||||
for (Object item : collection) {
|
||||
((BoolQueryBuilder) query).mustNot(queryStringQuery(item.toString()).field(fieldName));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,9 +16,27 @@
|
||||
package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.core.*;
|
||||
import com.fasterxml.jackson.databind.*;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.core.geo.CustomGeoModule;
|
||||
import org.springframework.data.geo.*;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.core.Version;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* DocumentMapper using jackson
|
||||
@@ -34,6 +52,7 @@ public class DefaultEntityMapper implements EntityMapper {
|
||||
objectMapper = new ObjectMapper();
|
||||
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
|
||||
objectMapper.registerModule(new CustomGeoModule());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+45
-28
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,28 +18,28 @@ package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import 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.base.Strings;
|
||||
import org.elasticsearch.common.jackson.core.JsonEncoding;
|
||||
import org.elasticsearch.common.jackson.core.JsonFactory;
|
||||
import org.elasticsearch.common.jackson.core.JsonGenerator;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.SearchHitField;
|
||||
import org.elasticsearch.search.facet.Facet;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.elasticsearch.ElasticsearchException;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.core.facet.DefaultFacetMapper;
|
||||
import org.springframework.data.elasticsearch.core.facet.FacetResult;
|
||||
import org.springframework.data.elasticsearch.annotations.ScriptedField;
|
||||
import org.springframework.data.elasticsearch.core.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;
|
||||
@@ -47,6 +47,9 @@ import org.springframework.data.mapping.context.MappingContext;
|
||||
|
||||
/**
|
||||
* @author Artur Konczak
|
||||
* @author Petar Tahchiev
|
||||
* @author Young Gu
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class DefaultResultMapper extends AbstractResultMapper {
|
||||
|
||||
@@ -73,34 +76,50 @@ public class DefaultResultMapper extends AbstractResultMapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> FacetedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
|
||||
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
|
||||
long totalHits = response.getHits().totalHits();
|
||||
List<T> results = new ArrayList<T>();
|
||||
for (SearchHit hit : response.getHits()) {
|
||||
if (hit != null) {
|
||||
T result = null;
|
||||
if (!Strings.isNullOrEmpty(hit.sourceAsString())) {
|
||||
if (StringUtils.isNotBlank(hit.sourceAsString())) {
|
||||
result = mapEntity(hit.sourceAsString(), clazz);
|
||||
} else {
|
||||
result = mapEntity(hit.getFields().values(), clazz);
|
||||
}
|
||||
setPersistentEntityId(result, hit.getId(), clazz);
|
||||
populateScriptFields(result, hit);
|
||||
results.add(result);
|
||||
}
|
||||
}
|
||||
List<FacetResult> facets = new ArrayList<FacetResult>();
|
||||
if (response.getFacets() != null) {
|
||||
for (Facet facet : response.getFacets()) {
|
||||
FacetResult facetResult = DefaultFacetMapper.parse(facet);
|
||||
if (facetResult != null) {
|
||||
facets.add(facetResult);
|
||||
|
||||
return new AggregatedPageImpl<T>(results, pageable, totalHits, response.getAggregations());
|
||||
}
|
||||
|
||||
private <T> void populateScriptFields(T result, SearchHit hit) {
|
||||
if (hit.getFields() != null && !hit.getFields().isEmpty() && result != null) {
|
||||
for (java.lang.reflect.Field field : result.getClass().getDeclaredFields()) {
|
||||
ScriptedField scriptedField = field.getAnnotation(ScriptedField.class);
|
||||
if (scriptedField != null) {
|
||||
String name = scriptedField.name().isEmpty() ? field.getName() : scriptedField.name();
|
||||
SearchHitField searchHitField = hit.getFields().get(name);
|
||||
if (searchHitField != null) {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
field.set(result, searchHitField.getValue());
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ElasticsearchException("failed to set scripted field: " + name + " with value: "
|
||||
+ searchHitField.getValue(), e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new ElasticsearchException("failed to access scripted field: " + name, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new FacetedPageImpl<T>(results, pageable, totalHits, facets);
|
||||
}
|
||||
|
||||
|
||||
private <T> T mapEntity(Collection<SearchHitField> values, Class<T> clazz) {
|
||||
return mapEntity(buildJSONFromFields(values), clazz);
|
||||
}
|
||||
@@ -145,6 +164,7 @@ public class DefaultResultMapper extends AbstractResultMapper {
|
||||
for (MultiGetItemResponse response : responses.getResponses()) {
|
||||
if (!response.isFailed() && response.getResponse().isExists()) {
|
||||
T result = mapEntity(response.getResponse().getSourceAsString(), clazz);
|
||||
setPersistentEntityId(result, response.getResponse().getId(), clazz);
|
||||
list.add(result);
|
||||
}
|
||||
}
|
||||
@@ -152,18 +172,15 @@ public class DefaultResultMapper extends AbstractResultMapper {
|
||||
}
|
||||
|
||||
private <T> void setPersistentEntityId(T result, String id, Class<T> clazz) {
|
||||
|
||||
if (mappingContext != null && clazz.isAnnotationPresent(Document.class)) {
|
||||
PersistentProperty<ElasticsearchPersistentProperty> idProperty = mappingContext.getPersistentEntity(clazz).getIdProperty();
|
||||
|
||||
ElasticsearchPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(clazz);
|
||||
PersistentProperty<?> idProperty = persistentEntity.getIdProperty();
|
||||
|
||||
// Only deal with String because ES generated Ids are strings !
|
||||
if (idProperty != null && idProperty.getType().isAssignableFrom(String.class)) {
|
||||
Method setter = idProperty.getSetter();
|
||||
if (setter != null) {
|
||||
try {
|
||||
setter.invoke(result, id);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
persistentEntity.getPropertyAccessor(result).setProperty(idProperty, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+136
-28
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,15 +15,18 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import org.elasticsearch.action.update.UpdateResponse;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.cluster.metadata.AliasMetaData;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||
import org.springframework.data.elasticsearch.core.query.*;
|
||||
import org.springframework.data.util.CloseableIterator;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.elasticsearch.action.update.UpdateResponse;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||
import org.springframework.data.elasticsearch.core.query.*;
|
||||
|
||||
/**
|
||||
* ElasticsearchOperations
|
||||
@@ -39,6 +42,11 @@ public interface ElasticsearchOperations {
|
||||
*/
|
||||
ElasticsearchConverter getElasticsearchConverter();
|
||||
|
||||
/**
|
||||
* @return elasticsearch client
|
||||
*/
|
||||
Client getClient();
|
||||
|
||||
/**
|
||||
* Create an index for a class
|
||||
*
|
||||
@@ -171,7 +179,7 @@ public interface ElasticsearchOperations {
|
||||
* @param clazz
|
||||
* @return
|
||||
*/
|
||||
<T> FacetedPage<T> queryForPage(SearchQuery query, Class<T> clazz);
|
||||
<T> Page<T> queryForPage(SearchQuery query, Class<T> clazz);
|
||||
|
||||
/**
|
||||
* Execute the query against elasticsearch and return result as {@link Page} using custom mapper
|
||||
@@ -180,7 +188,7 @@ public interface ElasticsearchOperations {
|
||||
* @param clazz
|
||||
* @return
|
||||
*/
|
||||
<T> FacetedPage<T> queryForPage(SearchQuery query, Class<T> clazz, SearchResultMapper mapper);
|
||||
<T> Page<T> queryForPage(SearchQuery query, Class<T> clazz, SearchResultMapper mapper);
|
||||
|
||||
/**
|
||||
* Execute the query against elasticsearch and return result as {@link Page}
|
||||
@@ -198,7 +206,7 @@ public interface ElasticsearchOperations {
|
||||
* @param clazz
|
||||
* @return
|
||||
*/
|
||||
<T> FacetedPage<T> queryForPage(StringQuery query, Class<T> clazz);
|
||||
<T> Page<T> queryForPage(StringQuery query, Class<T> clazz);
|
||||
|
||||
/**
|
||||
* Execute the query against elasticsearch and return result as {@link Page} using custom mapper
|
||||
@@ -207,7 +215,47 @@ public interface ElasticsearchOperations {
|
||||
* @param clazz
|
||||
* @return
|
||||
*/
|
||||
<T> FacetedPage<T> queryForPage(StringQuery query, Class<T> clazz, SearchResultMapper mapper);
|
||||
<T> Page<T> queryForPage(StringQuery query, Class<T> clazz, SearchResultMapper mapper);
|
||||
|
||||
/**
|
||||
* Executes the given {@link CriteriaQuery} against elasticsearch and return result as {@link CloseableIterator}.
|
||||
* <p>
|
||||
* Returns a {@link CloseableIterator} that wraps an Elasticsearch scroll context that needs to be closed in case of error.
|
||||
*
|
||||
* @param <T> element return type
|
||||
* @param query
|
||||
* @param clazz
|
||||
* @return
|
||||
* @since 1.3
|
||||
*/
|
||||
<T> CloseableIterator<T> stream(CriteriaQuery query, Class<T> clazz);
|
||||
|
||||
/**
|
||||
* Executes the given {@link SearchQuery} against elasticsearch and return result as {@link CloseableIterator}.
|
||||
* <p>
|
||||
* Returns a {@link CloseableIterator} that wraps an Elasticsearch scroll context that needs to be closed in case of error.
|
||||
*
|
||||
* @param <T> element return type
|
||||
* @param query
|
||||
* @param clazz
|
||||
* @return
|
||||
* @since 1.3
|
||||
*/
|
||||
<T> CloseableIterator<T> stream(SearchQuery query, Class<T> clazz);
|
||||
|
||||
/**
|
||||
* Executes the given {@link SearchQuery} against elasticsearch and return result as {@link CloseableIterator} using custom mapper.
|
||||
* <p>
|
||||
* Returns a {@link CloseableIterator} that wraps an Elasticsearch scroll context that needs to be closed in case of error.
|
||||
*
|
||||
* @param <T> element return type
|
||||
* @param query
|
||||
* @param clazz
|
||||
* @param mapper
|
||||
* @return
|
||||
* @since 1.3
|
||||
*/
|
||||
<T> CloseableIterator<T> stream(SearchQuery query, Class<T> clazz, SearchResultMapper mapper);
|
||||
|
||||
/**
|
||||
* Execute the criteria query against elasticsearch and return result as {@link List}
|
||||
@@ -323,6 +371,13 @@ public interface ElasticsearchOperations {
|
||||
*/
|
||||
void bulkIndex(List<IndexQuery> queries);
|
||||
|
||||
/**
|
||||
* Bulk update all objects. Will do update
|
||||
*
|
||||
* @param queries
|
||||
*/
|
||||
void bulkUpdate(List<UpdateQuery> queries);
|
||||
|
||||
/**
|
||||
* Delete the one object with provided id
|
||||
*
|
||||
@@ -333,6 +388,14 @@ public interface ElasticsearchOperations {
|
||||
*/
|
||||
String delete(String indexName, String type, String id);
|
||||
|
||||
|
||||
/**
|
||||
* Delete all records matching the criteria
|
||||
*
|
||||
* @param clazz
|
||||
* @param criteriaQuery
|
||||
*/
|
||||
<T> void delete(CriteriaQuery criteriaQuery, Class<T> clazz);
|
||||
/**
|
||||
* Delete the one object with provided id
|
||||
*
|
||||
@@ -374,14 +437,6 @@ public interface ElasticsearchOperations {
|
||||
*/
|
||||
boolean deleteIndex(String indexName);
|
||||
|
||||
/**
|
||||
* Deletes a type in an index
|
||||
*
|
||||
* @param index
|
||||
* @param type
|
||||
*/
|
||||
void deleteType(String index, String type);
|
||||
|
||||
/**
|
||||
* check if index is exists
|
||||
*
|
||||
@@ -412,28 +467,70 @@ public interface ElasticsearchOperations {
|
||||
* refresh the index
|
||||
*
|
||||
* @param indexName
|
||||
* @param waitForOperation
|
||||
*
|
||||
*/
|
||||
void refresh(String indexName, boolean waitForOperation);
|
||||
void refresh(String indexName);
|
||||
|
||||
/**
|
||||
* refresh the index
|
||||
*
|
||||
* @param clazz
|
||||
* @param waitForOperation
|
||||
*
|
||||
*/
|
||||
<T> void refresh(Class<T> clazz, boolean waitForOperation);
|
||||
<T> void refresh(Class<T> clazz);
|
||||
|
||||
/**
|
||||
* Returns scroll id for criteria query
|
||||
*
|
||||
* @param query The criteria query.
|
||||
* @param scrollTimeInMillis The time in millisecond for scroll feature
|
||||
* {@link org.elasticsearch.action.search.SearchRequestBuilder#setScroll(org.elasticsearch.common.unit.TimeValue)}.
|
||||
* @param noFields The no fields support
|
||||
* {@link org.elasticsearch.action.search.SearchRequestBuilder#setNoFields()}.
|
||||
* @return The scan id for input query.
|
||||
*/
|
||||
String scan(CriteriaQuery query, long scrollTimeInMillis, boolean noFields);
|
||||
|
||||
/**
|
||||
* Returns scroll id for criteria query
|
||||
*
|
||||
* @param query The criteria query.
|
||||
* @param scrollTimeInMillis The time in millisecond for scroll feature
|
||||
* {@link org.elasticsearch.action.search.SearchRequestBuilder#setScroll(org.elasticsearch.common.unit.TimeValue)}.
|
||||
* @param noFields The no fields support
|
||||
* {@link org.elasticsearch.action.search.SearchRequestBuilder#setNoFields()}.
|
||||
* @param clazz The class of entity to retrieve.
|
||||
* @param <T> The type of entity to retrieve.
|
||||
* @return The scan id for input query.
|
||||
*/
|
||||
<T> String scan(CriteriaQuery query, long scrollTimeInMillis, boolean noFields, Class<T> clazz);
|
||||
|
||||
/**
|
||||
* Returns scroll id for scan query
|
||||
*
|
||||
* @param query
|
||||
* @param scrollTimeInMillis
|
||||
* @param noFields
|
||||
* @return
|
||||
* @param query The search query.
|
||||
* @param scrollTimeInMillis The time in millisecond for scroll feature
|
||||
* {@link org.elasticsearch.action.search.SearchRequestBuilder#setScroll(org.elasticsearch.common.unit.TimeValue)}.
|
||||
* @param noFields The no fields support
|
||||
* {@link org.elasticsearch.action.search.SearchRequestBuilder#setNoFields()}.
|
||||
* @return The scan id for input query.
|
||||
*/
|
||||
String scan(SearchQuery query, long scrollTimeInMillis, boolean noFields);
|
||||
|
||||
/**
|
||||
* Returns scroll id for scan query
|
||||
*
|
||||
* @param query The search query.
|
||||
* @param scrollTimeInMillis The time in millisecond for scroll feature
|
||||
* {@link org.elasticsearch.action.search.SearchRequestBuilder#setScroll(org.elasticsearch.common.unit.TimeValue)}.
|
||||
* @param noFields The no fields support
|
||||
* {@link org.elasticsearch.action.search.SearchRequestBuilder#setNoFields()}.
|
||||
* @param clazz The class of entity to retrieve.
|
||||
* @param <T> The type of entity to retrieve.
|
||||
* @return The scan id for input query.
|
||||
*/
|
||||
<T> String scan(SearchQuery query, long scrollTimeInMillis, boolean noFields, Class<T> clazz);
|
||||
|
||||
/**
|
||||
* Scrolls the results for give scroll id
|
||||
*
|
||||
@@ -456,6 +553,14 @@ public interface ElasticsearchOperations {
|
||||
*/
|
||||
<T> Page<T> scroll(String scrollId, long scrollTimeInMillis, SearchResultMapper mapper);
|
||||
|
||||
/**
|
||||
* Clears the search contexts associated with specified scroll ids.
|
||||
*
|
||||
* @param scrollId
|
||||
*
|
||||
*/
|
||||
<T> void clearScroll(String scrollId);
|
||||
|
||||
/**
|
||||
* more like this query to search for documents that are "like" a specific document.
|
||||
*
|
||||
@@ -488,8 +593,11 @@ public interface ElasticsearchOperations {
|
||||
* @param indexName
|
||||
* @return
|
||||
*/
|
||||
Set<String> queryForAlias(String indexName);
|
||||
List<AliasMetaData> queryForAlias(String indexName);
|
||||
|
||||
|
||||
<T> T query(SearchQuery query, ResultsExtractor<T> resultsExtractor);
|
||||
|
||||
|
||||
ElasticsearchPersistentEntity getPersistentEntityFor(Class clazz);
|
||||
}
|
||||
|
||||
+367
-164
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,14 +15,15 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
|
||||
import static org.apache.commons.lang.StringUtils.*;
|
||||
import static org.apache.commons.lang.StringUtils.isNotBlank;
|
||||
import static org.apache.commons.lang.StringUtils.isBlank;
|
||||
import static org.elasticsearch.action.search.SearchType.*;
|
||||
import static org.elasticsearch.client.Requests.*;
|
||||
import static org.elasticsearch.cluster.metadata.AliasAction.Type.*;
|
||||
import static org.elasticsearch.common.collect.Sets.*;
|
||||
import static org.elasticsearch.index.VersionType.*;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.*;
|
||||
import static org.springframework.data.elasticsearch.core.MappingBuilder.*;
|
||||
import static org.springframework.util.CollectionUtils.isEmpty;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
@@ -30,12 +31,10 @@ import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.elasticsearch.action.ListenableActionFuture;
|
||||
import org.elasticsearch.action.admin.cluster.state.ClusterStateRequest;
|
||||
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
|
||||
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
|
||||
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.mapping.delete.DeleteMappingRequest;
|
||||
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequestBuilder;
|
||||
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
|
||||
@@ -48,7 +47,6 @@ import org.elasticsearch.action.get.MultiGetRequest;
|
||||
import org.elasticsearch.action.get.MultiGetRequestBuilder;
|
||||
import org.elasticsearch.action.get.MultiGetResponse;
|
||||
import org.elasticsearch.action.index.IndexRequestBuilder;
|
||||
import org.elasticsearch.action.mlt.MoreLikeThisRequestBuilder;
|
||||
import org.elasticsearch.action.search.SearchRequestBuilder;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.action.search.SearchType;
|
||||
@@ -59,17 +57,15 @@ import org.elasticsearch.action.update.UpdateResponse;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.client.Requests;
|
||||
import org.elasticsearch.cluster.metadata.AliasAction;
|
||||
import org.elasticsearch.cluster.metadata.MappingMetaData;
|
||||
import org.elasticsearch.common.collect.ImmutableOpenMap;
|
||||
import org.elasticsearch.cluster.metadata.AliasMetaData;
|
||||
import org.elasticsearch.common.collect.MapBuilder;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.index.query.FilterBuilder;
|
||||
import org.elasticsearch.index.query.MoreLikeThisQueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
||||
import org.elasticsearch.search.facet.FacetBuilder;
|
||||
import org.elasticsearch.search.highlight.HighlightBuilder;
|
||||
import org.elasticsearch.search.sort.SortBuilder;
|
||||
import org.elasticsearch.search.sort.SortOrder;
|
||||
@@ -80,12 +76,13 @@ import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.*;
|
||||
import org.springframework.data.elasticsearch.ElasticsearchException;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Mapping;
|
||||
import org.springframework.data.elasticsearch.annotations.Setting;
|
||||
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
|
||||
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
|
||||
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
|
||||
@@ -93,6 +90,7 @@ import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersiste
|
||||
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
||||
import org.springframework.data.elasticsearch.core.query.*;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.util.CloseableIterator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -102,6 +100,10 @@ import org.springframework.util.Assert;
|
||||
* @author Mohsin Husen
|
||||
* @author Artur Konczak
|
||||
* @author Kevin Leturc
|
||||
* @author Mason Chan
|
||||
* @author Young Gu
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Janssen
|
||||
*/
|
||||
|
||||
public class ElasticsearchTemplate implements ElasticsearchOperations, ApplicationContextAware {
|
||||
@@ -113,26 +115,39 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
private String searchTimeout;
|
||||
|
||||
public ElasticsearchTemplate(Client client) {
|
||||
this(client, null, null);
|
||||
this(client, new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext()));
|
||||
}
|
||||
|
||||
public ElasticsearchTemplate(Client client, EntityMapper entityMapper) {
|
||||
this(client, null, new DefaultResultMapper(entityMapper));
|
||||
this(client, new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext()), entityMapper);
|
||||
}
|
||||
|
||||
public ElasticsearchTemplate(Client client, ElasticsearchConverter elasticsearchConverter, EntityMapper entityMapper) {
|
||||
this(client, elasticsearchConverter, new DefaultResultMapper(elasticsearchConverter.getMappingContext(), entityMapper));
|
||||
}
|
||||
|
||||
public ElasticsearchTemplate(Client client, ResultsMapper resultsMapper) {
|
||||
this(client, null, resultsMapper);
|
||||
this(client, new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext()), resultsMapper);
|
||||
}
|
||||
|
||||
public ElasticsearchTemplate(Client client, ElasticsearchConverter elasticsearchConverter) {
|
||||
this(client, elasticsearchConverter, null);
|
||||
this(client, elasticsearchConverter, new DefaultResultMapper(elasticsearchConverter.getMappingContext()));
|
||||
}
|
||||
|
||||
public ElasticsearchTemplate(Client client, ElasticsearchConverter elasticsearchConverter, ResultsMapper resultsMapper) {
|
||||
|
||||
Assert.notNull(client, "Client must not be null!");
|
||||
Assert.notNull(elasticsearchConverter, "ElasticsearchConverter must not be null!");
|
||||
Assert.notNull(resultsMapper, "ResultsMapper must not be null!");
|
||||
|
||||
this.client = client;
|
||||
this.elasticsearchConverter = (elasticsearchConverter == null) ? new MappingElasticsearchConverter(
|
||||
new SimpleElasticsearchMappingContext()) : elasticsearchConverter;
|
||||
this.resultsMapper = (resultsMapper == null) ? new DefaultResultMapper(this.elasticsearchConverter.getMappingContext()) : resultsMapper;
|
||||
this.elasticsearchConverter = elasticsearchConverter;
|
||||
this.resultsMapper = resultsMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Client getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
public void setSearchTimeout(String searchTimeout) {
|
||||
@@ -252,12 +267,12 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> FacetedPage<T> queryForPage(SearchQuery query, Class<T> clazz) {
|
||||
public <T> AggregatedPage<T> queryForPage(SearchQuery query, Class<T> clazz) {
|
||||
return queryForPage(query, clazz, resultsMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> FacetedPage<T> queryForPage(SearchQuery query, Class<T> clazz, SearchResultMapper mapper) {
|
||||
public <T> AggregatedPage<T> queryForPage(SearchQuery query, Class<T> clazz, SearchResultMapper mapper) {
|
||||
SearchResponse response = doSearch(prepareSearch(query, clazz), query);
|
||||
return mapper.mapResults(response, clazz, query.getPageable());
|
||||
}
|
||||
@@ -296,7 +311,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
@Override
|
||||
public <T> Page<T> queryForPage(CriteriaQuery criteriaQuery, Class<T> clazz) {
|
||||
QueryBuilder elasticsearchQuery = new CriteriaQueryProcessor().createQueryFromCriteria(criteriaQuery.getCriteria());
|
||||
FilterBuilder elasticsearchFilter = new CriteriaFilterProcessor().createFilterFromCriteria(criteriaQuery.getCriteria());
|
||||
QueryBuilder elasticsearchFilter = new CriteriaFilterProcessor().createFilterFromCriteria(criteriaQuery.getCriteria());
|
||||
SearchRequestBuilder searchRequestBuilder = prepareSearch(criteriaQuery, clazz);
|
||||
|
||||
if (elasticsearchQuery != null) {
|
||||
@@ -311,6 +326,9 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
|
||||
if (elasticsearchFilter != null)
|
||||
searchRequestBuilder.setPostFilter(elasticsearchFilter);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("doSearch query:\n" + searchRequestBuilder.toString());
|
||||
}
|
||||
|
||||
SearchResponse response = getSearchResponse(searchRequestBuilder
|
||||
.execute());
|
||||
@@ -318,20 +336,98 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> FacetedPage<T> queryForPage(StringQuery query, Class<T> clazz) {
|
||||
public <T> Page<T> queryForPage(StringQuery query, Class<T> clazz) {
|
||||
return queryForPage(query, clazz, resultsMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> FacetedPage<T> queryForPage(StringQuery query, Class<T> clazz, SearchResultMapper mapper) {
|
||||
public <T> Page<T> queryForPage(StringQuery query, Class<T> clazz, SearchResultMapper mapper) {
|
||||
SearchResponse response = getSearchResponse(prepareSearch(query, clazz).setQuery(query.getSource()).execute());
|
||||
return mapper.mapResults(response, clazz, query.getPageable());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> CloseableIterator<T> stream(CriteriaQuery query, Class<T> clazz) {
|
||||
final long scrollTimeInMillis = TimeValue.timeValueMinutes(1).millis();
|
||||
final String initScrollId = scan(query, scrollTimeInMillis, false, clazz);
|
||||
return doStream(initScrollId, scrollTimeInMillis, clazz, resultsMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> CloseableIterator<T> stream(SearchQuery query, Class<T> clazz) {
|
||||
return stream(query, clazz, resultsMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> CloseableIterator<T> stream(SearchQuery query, final Class<T> clazz, final SearchResultMapper mapper) {
|
||||
final long scrollTimeInMillis = TimeValue.timeValueMinutes(1).millis();
|
||||
final String initScrollId = scan(query, scrollTimeInMillis, false, clazz);
|
||||
return doStream(initScrollId, scrollTimeInMillis, clazz, mapper);
|
||||
}
|
||||
|
||||
private <T> CloseableIterator<T> doStream(final String initScrollId, final long scrollTimeInMillis, final Class<T> clazz, final SearchResultMapper mapper) {
|
||||
return new CloseableIterator<T>() {
|
||||
|
||||
/** As we couldn't retrieve single result with scroll, store current hits. */
|
||||
private volatile Iterator<T> currentHits;
|
||||
|
||||
/** The scroll id. */
|
||||
private volatile String scrollId = initScrollId;
|
||||
|
||||
/** If stream is finished (ie: cluster returns no results. */
|
||||
private volatile boolean finished;
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
// Clear scroll on cluster only in case of error (cause elasticsearch auto clear scroll when it's done)
|
||||
if (!finished && scrollId != null && currentHits != null && currentHits.hasNext()) {
|
||||
client.prepareClearScroll().addScrollId(scrollId).execute().actionGet();
|
||||
}
|
||||
} finally {
|
||||
currentHits = null;
|
||||
scrollId = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
// Test if stream is finished
|
||||
if (finished) {
|
||||
return false;
|
||||
}
|
||||
// Test if it remains hits
|
||||
if (currentHits == null || !currentHits.hasNext()) {
|
||||
// Do a new request
|
||||
SearchResponse response = getSearchResponse(client.prepareSearchScroll(scrollId)
|
||||
.setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)).execute());
|
||||
// Save hits and scroll id
|
||||
currentHits = mapper.mapResults(response, clazz, null).iterator();
|
||||
finished = !currentHits.hasNext();
|
||||
scrollId = response.getScrollId();
|
||||
}
|
||||
return currentHits.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
if (hasNext()) {
|
||||
return currentHits.next();
|
||||
}
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("remove");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> long count(CriteriaQuery criteriaQuery, Class<T> clazz) {
|
||||
QueryBuilder elasticsearchQuery = new CriteriaQueryProcessor().createQueryFromCriteria(criteriaQuery.getCriteria());
|
||||
FilterBuilder elasticsearchFilter = new CriteriaFilterProcessor().createFilterFromCriteria(criteriaQuery.getCriteria());
|
||||
QueryBuilder elasticsearchFilter = new CriteriaFilterProcessor().createFilterFromCriteria(criteriaQuery.getCriteria());
|
||||
|
||||
if (elasticsearchFilter == null) {
|
||||
return doCount(prepareCount(criteriaQuery, clazz), elasticsearchQuery);
|
||||
@@ -344,7 +440,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
@Override
|
||||
public <T> long count(SearchQuery searchQuery, Class<T> clazz) {
|
||||
QueryBuilder elasticsearchQuery = searchQuery.getQuery();
|
||||
FilterBuilder elasticsearchFilter = searchQuery.getFilter();
|
||||
QueryBuilder elasticsearchFilter = searchQuery.getFilter();
|
||||
|
||||
if (elasticsearchFilter == null) {
|
||||
return doCount(prepareCount(searchQuery, clazz), elasticsearchQuery);
|
||||
@@ -371,7 +467,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
return countRequestBuilder.execute().actionGet().getCount();
|
||||
}
|
||||
|
||||
private long doCount(SearchRequestBuilder searchRequestBuilder, QueryBuilder elasticsearchQuery, FilterBuilder elasticsearchFilter) {
|
||||
private long doCount(SearchRequestBuilder searchRequestBuilder, QueryBuilder elasticsearchQuery, QueryBuilder elasticsearchFilter) {
|
||||
if (elasticsearchQuery != null) {
|
||||
searchRequestBuilder.setQuery(elasticsearchQuery);
|
||||
} else {
|
||||
@@ -385,8 +481,8 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
}
|
||||
|
||||
private <T> CountRequestBuilder prepareCount(Query query, Class<T> clazz) {
|
||||
String indexName[] = isNotEmpty(query.getIndices()) ? query.getIndices().toArray(new String[query.getIndices().size()]) : retrieveIndexNameFromPersistentEntity(clazz);
|
||||
String types[] = isNotEmpty(query.getTypes()) ? query.getTypes().toArray(new String[query.getTypes().size()]) : retrieveTypeFromPersistentEntity(clazz);
|
||||
String indexName[] = !isEmpty(query.getIndices()) ? query.getIndices().toArray(new String[query.getIndices().size()]) : retrieveIndexNameFromPersistentEntity(clazz);
|
||||
String types[] = !isEmpty(query.getTypes()) ? query.getTypes().toArray(new String[query.getTypes().size()]) : retrieveTypeFromPersistentEntity(clazz);
|
||||
|
||||
Assert.notNull(indexName, "No index defined for Query");
|
||||
|
||||
@@ -405,8 +501,8 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
|
||||
private <T> MultiGetResponse getMultiResponse(Query searchQuery, Class<T> clazz) {
|
||||
|
||||
String indexName = isNotEmpty(searchQuery.getIndices()) ? searchQuery.getIndices().get(0) : getPersistentEntityFor(clazz).getIndexName();
|
||||
String type = isNotEmpty(searchQuery.getTypes()) ? searchQuery.getTypes().get(0) : getPersistentEntityFor(clazz).getIndexType();
|
||||
String indexName = !isEmpty(searchQuery.getIndices()) ? searchQuery.getIndices().get(0) : getPersistentEntityFor(clazz).getIndexName();
|
||||
String type = !isEmpty(searchQuery.getTypes()) ? searchQuery.getTypes().get(0) : getPersistentEntityFor(clazz).getIndexType();
|
||||
|
||||
Assert.notNull(indexName, "No index defined for Query");
|
||||
Assert.notNull(type, "No type define for Query");
|
||||
@@ -447,6 +543,10 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
|
||||
@Override
|
||||
public UpdateResponse update(UpdateQuery query) {
|
||||
return this.prepareUpdate(query).execute().actionGet();
|
||||
}
|
||||
|
||||
private UpdateRequestBuilder prepareUpdate(UpdateQuery query) {
|
||||
String indexName = isNotBlank(query.getIndexName()) ? query.getIndexName() : getPersistentEntityFor(query.getClazz()).getIndexName();
|
||||
String type = isNotBlank(query.getType()) ? query.getType() : getPersistentEntityFor(query.getClazz()).getIndexType();
|
||||
Assert.notNull(indexName, "No index defined for Query");
|
||||
@@ -454,16 +554,22 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
Assert.notNull(query.getId(), "No Id define for Query");
|
||||
Assert.notNull(query.getUpdateRequest(), "No IndexRequest define for Query");
|
||||
UpdateRequestBuilder updateRequestBuilder = client.prepareUpdate(indexName, type, query.getId());
|
||||
if (query.DoUpsert()) {
|
||||
updateRequestBuilder.setDocAsUpsert(true)
|
||||
.setDoc(query.getUpdateRequest().doc())
|
||||
.setScript(query.getUpdateRequest().script(), query.getUpdateRequest().scriptType())
|
||||
.setScriptParams(query.getUpdateRequest().scriptParams())
|
||||
.setScriptLang(query.getUpdateRequest().scriptLang());
|
||||
updateRequestBuilder.setRouting(query.getUpdateRequest().routing());
|
||||
|
||||
if (query.getUpdateRequest().script() == null) {
|
||||
// doc
|
||||
if (query.DoUpsert()) {
|
||||
updateRequestBuilder.setDocAsUpsert(true)
|
||||
.setDoc(query.getUpdateRequest().doc());
|
||||
} else {
|
||||
updateRequestBuilder.setDoc(query.getUpdateRequest().doc());
|
||||
}
|
||||
} else {
|
||||
updateRequestBuilder.setDoc(query.getUpdateRequest().doc());
|
||||
// or script
|
||||
updateRequestBuilder.setScript(query.getUpdateRequest().script());
|
||||
}
|
||||
return updateRequestBuilder.execute().actionGet();
|
||||
|
||||
return updateRequestBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -486,6 +592,26 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bulkUpdate(List<UpdateQuery> queries) {
|
||||
BulkRequestBuilder bulkRequest = client.prepareBulk();
|
||||
for (UpdateQuery query : queries) {
|
||||
bulkRequest.add(prepareUpdate(query));
|
||||
}
|
||||
BulkResponse bulkResponse = bulkRequest.execute().actionGet();
|
||||
if (bulkResponse.hasFailures()) {
|
||||
Map<String, String> failedDocuments = new HashMap<String, String>();
|
||||
for (BulkItemResponse item : bulkResponse.getItems()) {
|
||||
if (item.isFailed())
|
||||
failedDocuments.put(item.getId(), item.getFailureMessage());
|
||||
}
|
||||
throw new ElasticsearchException(
|
||||
"Bulk indexing has failures. Use ElasticsearchException.getFailedDocuments() for detailed messages ["
|
||||
+ failedDocuments + "]", failedDocuments
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> boolean indexExists(Class<T> clazz) {
|
||||
return indexExists(getPersistentEntityFor(clazz).getIndexName());
|
||||
@@ -499,7 +625,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
@Override
|
||||
public boolean typeExists(String index, String type) {
|
||||
return client.admin().cluster().prepareState().execute().actionGet()
|
||||
.getState().metaData().index(index).mappings().containsKey(type);
|
||||
.getState().metaData().index(index).getMappings().containsKey(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -516,15 +642,6 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteType(String index, String type) {
|
||||
ImmutableOpenMap<String, MappingMetaData> mappings = client.admin().cluster().prepareState().execute().actionGet()
|
||||
.getState().metaData().index(index).mappings();
|
||||
if (mappings.containsKey(type)) {
|
||||
client.admin().indices().deleteMapping(new DeleteMappingRequest(index).types(type)).actionGet();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String delete(String indexName, String type, String id) {
|
||||
return client.prepareDelete(indexName, type, id).execute().actionGet().getId();
|
||||
@@ -538,44 +655,146 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
|
||||
@Override
|
||||
public <T> void delete(DeleteQuery deleteQuery, Class<T> clazz) {
|
||||
ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(clazz);
|
||||
client.prepareDeleteByQuery(persistentEntity.getIndexName()).setTypes(persistentEntity.getIndexType())
|
||||
.setQuery(deleteQuery.getQuery()).execute().actionGet();
|
||||
|
||||
String indexName = isNotBlank(deleteQuery.getIndex()) ? deleteQuery.getIndex() : getPersistentEntityFor(clazz).getIndexName();
|
||||
String typeName = isNotBlank(deleteQuery.getType()) ? deleteQuery.getType() : getPersistentEntityFor(clazz).getIndexType();
|
||||
Integer pageSize = deleteQuery.getPageSize() != null ? deleteQuery.getPageSize() : 1000;
|
||||
Long scrollTimeInMillis = deleteQuery.getScrollTimeInMillis() != null ? deleteQuery.getScrollTimeInMillis() : 10000l;
|
||||
|
||||
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(deleteQuery.getQuery())
|
||||
.withIndices(indexName)
|
||||
.withTypes(typeName)
|
||||
.withPageable(new PageRequest(0, pageSize))
|
||||
.build();
|
||||
|
||||
String scrollId = scan(searchQuery, scrollTimeInMillis, true);
|
||||
|
||||
BulkRequestBuilder bulkRequestBuilder = client.prepareBulk();
|
||||
List<String> ids = new ArrayList<String>();
|
||||
boolean hasRecords = true;
|
||||
while (hasRecords) {
|
||||
Page<String> page = scroll(scrollId, scrollTimeInMillis, new SearchResultMapper() {
|
||||
@Override
|
||||
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
|
||||
List<String> result = new ArrayList<String>();
|
||||
for (SearchHit searchHit : response.getHits()) {
|
||||
String id = searchHit.getId();
|
||||
result.add(id);
|
||||
}
|
||||
if (result.size() > 0) {
|
||||
return new AggregatedPageImpl<T>((List<T>) result);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
if (page != null && page.getContent().size() > 0) {
|
||||
ids.addAll(page.getContent());
|
||||
} else {
|
||||
hasRecords = false;
|
||||
}
|
||||
}
|
||||
|
||||
for(String id : ids) {
|
||||
bulkRequestBuilder.add(client.prepareDelete(indexName, typeName, id));
|
||||
}
|
||||
|
||||
if(bulkRequestBuilder.numberOfActions() > 0) {
|
||||
bulkRequestBuilder.execute().actionGet();
|
||||
}
|
||||
|
||||
clearScroll(scrollId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(DeleteQuery deleteQuery) {
|
||||
Assert.notNull(deleteQuery.getIndex(), "No index defined for Query");
|
||||
Assert.notNull(deleteQuery.getType(), "No type define for Query");
|
||||
client.prepareDeleteByQuery(deleteQuery.getIndex()).setTypes(deleteQuery.getType())
|
||||
.setQuery(deleteQuery.getQuery()).execute().actionGet();
|
||||
delete(deleteQuery, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void delete(CriteriaQuery criteriaQuery, Class<T> clazz) {
|
||||
QueryBuilder elasticsearchQuery = new CriteriaQueryProcessor().createQueryFromCriteria(criteriaQuery.getCriteria());
|
||||
Assert.notNull(elasticsearchQuery, "Query can not be null.");
|
||||
DeleteQuery deleteQuery = new DeleteQuery();
|
||||
deleteQuery.setQuery(elasticsearchQuery);
|
||||
delete(deleteQuery, clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String scan(CriteriaQuery criteriaQuery, long scrollTimeInMillis, boolean noFields) {
|
||||
return doScan(prepareScan(criteriaQuery, scrollTimeInMillis, noFields), criteriaQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> String scan(CriteriaQuery criteriaQuery, long scrollTimeInMillis, boolean noFields, Class<T> clazz) {
|
||||
return doScan(prepareScan(criteriaQuery, scrollTimeInMillis, noFields, clazz), criteriaQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String scan(SearchQuery searchQuery, long scrollTimeInMillis, boolean noFields) {
|
||||
Assert.notNull(searchQuery.getIndices(), "No index defined for Query");
|
||||
Assert.notNull(searchQuery.getTypes(), "No type define for Query");
|
||||
Assert.notNull(searchQuery.getPageable(), "Query.pageable is required for scan & scroll");
|
||||
return doScan(prepareScan(searchQuery, scrollTimeInMillis, noFields), searchQuery);
|
||||
}
|
||||
|
||||
SearchRequestBuilder requestBuilder = client.prepareSearch(toArray(searchQuery.getIndices())).setSearchType(SCAN)
|
||||
.setQuery(searchQuery.getQuery()).setTypes(toArray(searchQuery.getTypes()))
|
||||
@Override
|
||||
public <T> String scan(SearchQuery searchQuery, long scrollTimeInMillis, boolean noFields, Class<T> clazz) {
|
||||
return doScan(prepareScan(searchQuery, scrollTimeInMillis, noFields, clazz), searchQuery);
|
||||
}
|
||||
|
||||
private <T> SearchRequestBuilder prepareScan(Query query, long scrollTimeInMillis, boolean noFields, Class<T> clazz) {
|
||||
setPersistentEntityIndexAndType(query, clazz);
|
||||
return prepareScan(query, scrollTimeInMillis, noFields);
|
||||
}
|
||||
|
||||
private SearchRequestBuilder prepareScan(Query query, long scrollTimeInMillis, boolean noFields) {
|
||||
SearchRequestBuilder requestBuilder = client.prepareSearch(toArray(query.getIndices())).setSearchType(SCAN)
|
||||
.setTypes(toArray(query.getTypes()))
|
||||
.setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)).setFrom(0)
|
||||
.setSize(searchQuery.getPageable().getPageSize());
|
||||
.setSize(query.getPageable().getPageSize());
|
||||
|
||||
if (searchQuery.getFilter() != null) {
|
||||
requestBuilder.setPostFilter(searchQuery.getFilter());
|
||||
}
|
||||
|
||||
if (isNotEmpty(searchQuery.getFields())) {
|
||||
requestBuilder.addFields(toArray(searchQuery.getFields()));
|
||||
if (!isEmpty(query.getFields())) {
|
||||
requestBuilder.addFields(toArray(query.getFields()));
|
||||
}
|
||||
|
||||
if (noFields) {
|
||||
requestBuilder.setNoFields();
|
||||
}
|
||||
return requestBuilder;
|
||||
}
|
||||
|
||||
private String doScan(SearchRequestBuilder requestBuilder, CriteriaQuery criteriaQuery) {
|
||||
Assert.notNull(criteriaQuery.getIndices(), "No index defined for Query");
|
||||
Assert.notNull(criteriaQuery.getTypes(), "No type define for Query");
|
||||
Assert.notNull(criteriaQuery.getPageable(), "Query.pageable is required for scan & scroll");
|
||||
|
||||
QueryBuilder elasticsearchQuery = new CriteriaQueryProcessor().createQueryFromCriteria(criteriaQuery.getCriteria());
|
||||
QueryBuilder elasticsearchFilter = new CriteriaFilterProcessor().createFilterFromCriteria(criteriaQuery.getCriteria());
|
||||
|
||||
if (elasticsearchQuery != null) {
|
||||
requestBuilder.setQuery(elasticsearchQuery);
|
||||
} else {
|
||||
requestBuilder.setQuery(QueryBuilders.matchAllQuery());
|
||||
}
|
||||
|
||||
if (elasticsearchFilter != null) {
|
||||
requestBuilder.setPostFilter(elasticsearchFilter);
|
||||
}
|
||||
|
||||
return getSearchResponse(requestBuilder.execute()).getScrollId();
|
||||
}
|
||||
|
||||
private String doScan(SearchRequestBuilder requestBuilder, SearchQuery searchQuery) {
|
||||
Assert.notNull(searchQuery.getIndices(), "No index defined for Query");
|
||||
Assert.notNull(searchQuery.getTypes(), "No type define for Query");
|
||||
Assert.notNull(searchQuery.getPageable(), "Query.pageable is required for scan & scroll");
|
||||
|
||||
if (searchQuery.getFilter() != null) {
|
||||
requestBuilder.setPostFilter(searchQuery.getFilter());
|
||||
}
|
||||
|
||||
return getSearchResponse(requestBuilder.setQuery(searchQuery.getQuery()).execute()).getScrollId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Page<T> scroll(String scrollId, long scrollTimeInMillis, Class<T> clazz) {
|
||||
SearchResponse response = getSearchResponse(client.prepareSearchScroll(scrollId)
|
||||
@@ -590,9 +809,14 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
return mapper.mapResults(response, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearScroll(String scrollId) {
|
||||
client.prepareClearScroll().addScrollId(scrollId).execute().actionGet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Page<T> moreLikeThis(MoreLikeThisQuery query, Class<T> clazz) {
|
||||
int startRecord = 0;
|
||||
|
||||
ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(clazz);
|
||||
String indexName = isNotBlank(query.getIndexName()) ? query.getIndexName() : persistentEntity.getIndexName();
|
||||
String type = isNotBlank(query.getType()) ? query.getType() : persistentEntity.getIndexType();
|
||||
@@ -601,56 +825,35 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
Assert.notNull(type, "No 'type' defined for MoreLikeThisQuery");
|
||||
Assert.notNull(query.getId(), "No document id defined for MoreLikeThisQuery");
|
||||
|
||||
MoreLikeThisRequestBuilder requestBuilder = client.prepareMoreLikeThis(indexName, type, query.getId());
|
||||
MoreLikeThisQueryBuilder moreLikeThisQueryBuilder = moreLikeThisQuery()
|
||||
.addLikeItem(new MoreLikeThisQueryBuilder.Item(indexName, type, query.getId()));
|
||||
|
||||
if (query.getPageable() != null) {
|
||||
startRecord = query.getPageable().getPageNumber() * query.getPageable().getPageSize();
|
||||
requestBuilder.setSearchSize(query.getPageable().getPageSize());
|
||||
}
|
||||
requestBuilder.setSearchFrom(startRecord);
|
||||
|
||||
if (isNotEmpty(query.getSearchIndices())) {
|
||||
requestBuilder.setSearchIndices(toArray(query.getSearchIndices()));
|
||||
}
|
||||
if (isNotEmpty(query.getSearchTypes())) {
|
||||
requestBuilder.setSearchTypes(toArray(query.getSearchTypes()));
|
||||
}
|
||||
if (isNotEmpty(query.getFields())) {
|
||||
requestBuilder.setField(toArray(query.getFields()));
|
||||
}
|
||||
if (isNotBlank(query.getRouting())) {
|
||||
requestBuilder.setRouting(query.getRouting());
|
||||
}
|
||||
if (query.getPercentTermsToMatch() != null) {
|
||||
requestBuilder.setPercentTermsToMatch(query.getPercentTermsToMatch());
|
||||
}
|
||||
if (query.getMinTermFreq() != null) {
|
||||
requestBuilder.setMinTermFreq(query.getMinTermFreq());
|
||||
moreLikeThisQueryBuilder.minTermFreq(query.getMinTermFreq());
|
||||
}
|
||||
if (query.getMaxQueryTerms() != null) {
|
||||
requestBuilder.maxQueryTerms(query.getMaxQueryTerms());
|
||||
moreLikeThisQueryBuilder.maxQueryTerms(query.getMaxQueryTerms());
|
||||
}
|
||||
if (isNotEmpty(query.getStopWords())) {
|
||||
requestBuilder.setStopWords(toArray(query.getStopWords()));
|
||||
if (!isEmpty(query.getStopWords())) {
|
||||
moreLikeThisQueryBuilder.stopWords(toArray(query.getStopWords()));
|
||||
}
|
||||
if (query.getMinDocFreq() != null) {
|
||||
requestBuilder.setMinDocFreq(query.getMinDocFreq());
|
||||
moreLikeThisQueryBuilder.minDocFreq(query.getMinDocFreq());
|
||||
}
|
||||
if (query.getMaxDocFreq() != null) {
|
||||
requestBuilder.setMaxDocFreq(query.getMaxDocFreq());
|
||||
moreLikeThisQueryBuilder.maxDocFreq(query.getMaxDocFreq());
|
||||
}
|
||||
if (query.getMinWordLen() != null) {
|
||||
requestBuilder.setMinWordLen(query.getMinWordLen());
|
||||
moreLikeThisQueryBuilder.minWordLength(query.getMinWordLen());
|
||||
}
|
||||
if (query.getMaxWordLen() != null) {
|
||||
requestBuilder.setMaxWordLen(query.getMaxWordLen());
|
||||
moreLikeThisQueryBuilder.maxWordLength(query.getMaxWordLen());
|
||||
}
|
||||
if (query.getBoostTerms() != null) {
|
||||
requestBuilder.setBoostTerms(query.getBoostTerms());
|
||||
moreLikeThisQueryBuilder.boostTerms(query.getBoostTerms());
|
||||
}
|
||||
|
||||
SearchResponse response = getSearchResponse(requestBuilder.execute());
|
||||
return resultsMapper.mapResults(response, clazz, query.getPageable());
|
||||
return queryForPage(new NativeSearchQueryBuilder().withQuery(moreLikeThisQueryBuilder).build(), clazz);
|
||||
}
|
||||
|
||||
private SearchResponse doSearch(SearchRequestBuilder searchRequest, SearchQuery searchQuery) {
|
||||
@@ -658,19 +861,16 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
searchRequest.setPostFilter(searchQuery.getFilter());
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(searchQuery.getElasticsearchSorts())) {
|
||||
if (!isEmpty(searchQuery.getElasticsearchSorts())) {
|
||||
for (SortBuilder sort : searchQuery.getElasticsearchSorts()) {
|
||||
searchRequest.addSort(sort);
|
||||
}
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(searchQuery.getFacets())) {
|
||||
for (FacetRequest facetRequest : searchQuery.getFacets()) {
|
||||
FacetBuilder facet = facetRequest.getFacet();
|
||||
if (facetRequest.applyQueryFilter() && searchQuery.getFilter() != null) {
|
||||
facet.facetFilter(searchQuery.getFilter());
|
||||
}
|
||||
searchRequest.addFacet(facet);
|
||||
if (!searchQuery.getScriptFields().isEmpty()) {
|
||||
searchRequest.addField("_source");
|
||||
for (ScriptField scriptedField : searchQuery.getScriptFields()) {
|
||||
searchRequest.addScriptField(scriptedField.fieldName(), scriptedField.script());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -680,11 +880,23 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
}
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(searchQuery.getAggregations())) {
|
||||
if (!isEmpty(searchQuery.getIndicesBoost())) {
|
||||
for (IndexBoost indexBoost : searchQuery.getIndicesBoost()) {
|
||||
searchRequest.addIndexBoost(indexBoost.getIndexName(), indexBoost.getBoost());
|
||||
}
|
||||
}
|
||||
|
||||
if (!isEmpty(searchQuery.getAggregations())) {
|
||||
for (AbstractAggregationBuilder aggregationBuilder : searchQuery.getAggregations()) {
|
||||
searchRequest.addAggregation(aggregationBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isEmpty(searchQuery.getFacets())) {
|
||||
for (FacetRequest aggregatedFacet : searchQuery.getFacets()) {
|
||||
searchRequest.addAggregation(aggregatedFacet.getFacet());
|
||||
}
|
||||
}
|
||||
return getSearchResponse(searchRequest.setQuery(searchQuery.getQuery()).execute());
|
||||
}
|
||||
|
||||
@@ -730,6 +942,10 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
}
|
||||
|
||||
private <T> Map getDefaultSettings(ElasticsearchPersistentEntity<T> persistentEntity) {
|
||||
|
||||
if (persistentEntity.isUseServerConfiguration())
|
||||
return new HashMap();
|
||||
|
||||
return new MapBuilder<String, String>().put("index.number_of_shards", String.valueOf(persistentEntity.getShards()))
|
||||
.put("index.number_of_replicas", String.valueOf(persistentEntity.getReplicas()))
|
||||
.put("index.refresh_interval", persistentEntity.getRefreshInterval())
|
||||
@@ -749,12 +965,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
}
|
||||
|
||||
private <T> SearchRequestBuilder prepareSearch(Query query, Class<T> clazz) {
|
||||
if (query.getIndices().isEmpty()) {
|
||||
query.addIndices(retrieveIndexNameFromPersistentEntity(clazz));
|
||||
}
|
||||
if (query.getTypes().isEmpty()) {
|
||||
query.addTypes(retrieveTypeFromPersistentEntity(clazz));
|
||||
}
|
||||
setPersistentEntityIndexAndType(query, clazz);
|
||||
return prepareSearch(query);
|
||||
}
|
||||
|
||||
@@ -766,6 +977,11 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
SearchRequestBuilder searchRequestBuilder = client.prepareSearch(toArray(query.getIndices()))
|
||||
.setSearchType(query.getSearchType()).setTypes(toArray(query.getTypes()));
|
||||
|
||||
if (query.getSourceFilter() != null) {
|
||||
SourceFilter sourceFilter = query.getSourceFilter();
|
||||
searchRequestBuilder.setFetchSource(sourceFilter.getIncludes(), sourceFilter.getExcludes());
|
||||
}
|
||||
|
||||
if (query.getPageable() != null) {
|
||||
startRecord = query.getPageable().getPageNumber() * query.getPageable().getPageSize();
|
||||
searchRequestBuilder.setSize(query.getPageable().getPageSize());
|
||||
@@ -799,13 +1015,10 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
IndexRequestBuilder indexRequestBuilder = null;
|
||||
|
||||
if (query.getObject() != null) {
|
||||
String entityId = null;
|
||||
if (isDocument(query.getObject().getClass())) {
|
||||
entityId = getPersistentEntityId(query.getObject());
|
||||
}
|
||||
String id = isBlank(query.getId()) ? getPersistentEntityId(query.getObject()) : query.getId();
|
||||
// If we have a query id and a document id, do not ask ES to generate one.
|
||||
if (query.getId() != null && entityId != null) {
|
||||
indexRequestBuilder = client.prepareIndex(indexName, type, query.getId());
|
||||
if (id != null) {
|
||||
indexRequestBuilder = client.prepareIndex(indexName, type, id);
|
||||
} else {
|
||||
indexRequestBuilder = client.prepareIndex(indexName, type);
|
||||
}
|
||||
@@ -831,15 +1044,14 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(String indexName, boolean waitForOperation) {
|
||||
client.admin().indices().refresh(refreshRequest(indexName).force(waitForOperation)).actionGet();
|
||||
public void refresh(String indexName) {
|
||||
Assert.notNull(indexName, "No index defined for refresh()");
|
||||
client.admin().indices().refresh(refreshRequest(indexName)).actionGet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void refresh(Class<T> clazz, boolean waitForOperation) {
|
||||
ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(clazz);
|
||||
client.admin().indices()
|
||||
.refresh(refreshRequest(persistentEntity.getIndexName()).force(waitForOperation)).actionGet();
|
||||
public <T> void refresh(Class<T> clazz) {
|
||||
refresh(getPersistentEntityFor(clazz).getIndexName());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -870,49 +1082,43 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> queryForAlias(String indexName) {
|
||||
ClusterStateRequest clusterStateRequest = Requests.clusterStateRequest()
|
||||
.routingTable(true).nodes(true).indices(indexName);
|
||||
Iterator<String> iterator = client.admin().cluster().state(clusterStateRequest).actionGet().getState().getMetaData().aliases().keysIt();
|
||||
return newHashSet(iterator);
|
||||
public List<AliasMetaData> queryForAlias(String indexName) {
|
||||
return client.admin().indices().getAliases(new GetAliasesRequest().indices(indexName))
|
||||
.actionGet().getAliases().get(indexName);
|
||||
}
|
||||
|
||||
private ElasticsearchPersistentEntity getPersistentEntityFor(Class clazz) {
|
||||
@Override
|
||||
public ElasticsearchPersistentEntity getPersistentEntityFor(Class clazz) {
|
||||
Assert.isTrue(clazz.isAnnotationPresent(Document.class), "Unable to identify index name. " + clazz.getSimpleName()
|
||||
+ " is not a Document. Make sure the document class is annotated with @Document(indexName=\"foo\")");
|
||||
return elasticsearchConverter.getMappingContext().getPersistentEntity(clazz);
|
||||
}
|
||||
|
||||
private String getPersistentEntityId(Object entity) {
|
||||
PersistentProperty idProperty = getPersistentEntityFor(entity.getClass()).getIdProperty();
|
||||
if (idProperty != null) {
|
||||
Method getter = idProperty.getGetter();
|
||||
if (getter != null) {
|
||||
try {
|
||||
Object id = getter.invoke(entity);
|
||||
if (id != null) {
|
||||
return String.valueOf(id);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
ElasticsearchPersistentEntity<?> persistentEntity = getPersistentEntityFor(entity.getClass());
|
||||
Object identifier = persistentEntity.getIdentifierAccessor(entity).getIdentifier();
|
||||
|
||||
return identifier == null ? null : String.valueOf(identifier);
|
||||
}
|
||||
|
||||
private void setPersistentEntityId(Object entity, String id) {
|
||||
PersistentProperty idProperty = getPersistentEntityFor(entity.getClass()).getIdProperty();
|
||||
|
||||
ElasticsearchPersistentEntity<?> persistentEntity = getPersistentEntityFor(entity.getClass());
|
||||
PersistentProperty<?> idProperty = persistentEntity.getIdProperty();
|
||||
|
||||
// Only deal with String because ES generated Ids are strings !
|
||||
if (idProperty != null && idProperty.getType().isAssignableFrom(String.class)) {
|
||||
Method setter = idProperty.getSetter();
|
||||
if (setter != null) {
|
||||
try {
|
||||
setter.invoke(entity, id);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
persistentEntity.getPropertyAccessor(entity).setProperty(idProperty,id);
|
||||
}
|
||||
}
|
||||
|
||||
private void setPersistentEntityIndexAndType(Query query, Class clazz) {
|
||||
if (query.getIndices().isEmpty()) {
|
||||
query.addIndices(retrieveIndexNameFromPersistentEntity(clazz));
|
||||
}
|
||||
if (query.getTypes().isEmpty()) {
|
||||
query.addTypes(retrieveTypeFromPersistentEntity(clazz));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -956,10 +1162,6 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
return resultsMapper;
|
||||
}
|
||||
|
||||
private boolean isDocument(Class clazz) {
|
||||
return clazz.isAnnotationPresent(Document.class);
|
||||
}
|
||||
|
||||
public static String readFileFromClasspath(String url) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
|
||||
@@ -971,8 +1173,9 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
|
||||
bufferedReader = new BufferedReader(inputStreamReader);
|
||||
String line;
|
||||
|
||||
String lineSeparator = System.getProperty("line.separator");
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
stringBuilder.append(line);
|
||||
stringBuilder.append(line).append(lineSeparator);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug(String.format("Failed to load file from url: %s: %s", url, e.getMessage()));
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.springframework.data.elasticsearch.core.facet.FacetResult;
|
||||
* @author Artur Konczak
|
||||
* @author Jonathan Yan
|
||||
*/
|
||||
@Deprecated
|
||||
public interface FacetedPage<T> extends Page<T> {
|
||||
|
||||
boolean hasFacets();
|
||||
|
||||
@@ -15,14 +15,25 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.elasticsearch.search.aggregations.Aggregation;
|
||||
import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
|
||||
import org.elasticsearch.search.aggregations.bucket.range.Range;
|
||||
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
|
||||
import org.elasticsearch.search.aggregations.metrics.stats.extended.ExtendedStats;
|
||||
import org.elasticsearch.search.aggregations.metrics.sum.Sum;
|
||||
import org.joda.time.DateTime;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
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.*;
|
||||
|
||||
/**
|
||||
* Container for query result and facet results
|
||||
@@ -32,7 +43,8 @@ import org.springframework.data.elasticsearch.core.facet.FacetResult;
|
||||
* @author Artur Konczak
|
||||
* @author Jonathan Yan
|
||||
*/
|
||||
public class FacetedPageImpl<T> extends PageImpl<T> implements FacetedPage<T> {
|
||||
@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>();
|
||||
@@ -45,26 +57,74 @@ public class FacetedPageImpl<T> extends PageImpl<T> implements FacetedPage<T> {
|
||||
super(content, pageable, total);
|
||||
}
|
||||
|
||||
public FacetedPageImpl(List<T> content, Pageable pageable, long total, List<FacetResult> facets) {
|
||||
super(content, pageable, total);
|
||||
this.facets = facets;
|
||||
for (FacetResult facet : facets) {
|
||||
mapOfFacets.put(facet.getName(), facet);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFacets() {
|
||||
return CollectionUtils.isNotEmpty(facets);
|
||||
processAggregations();
|
||||
return facets != null && facets.size() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FacetResult> getFacets() {
|
||||
processAggregations();
|
||||
return facets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FacetResult getFacet(String name) {
|
||||
processAggregations();
|
||||
return mapOfFacets.get(name);
|
||||
}
|
||||
|
||||
private void addFacet(FacetResult facetResult) {
|
||||
facets.add(facetResult);
|
||||
mapOfFacets.put(facetResult.getName(), facetResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,12 +25,15 @@ 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.facet.FacetRequest;
|
||||
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
@@ -43,6 +46,7 @@ import org.springframework.data.util.TypeInformation;
|
||||
* @author Kevin Leturc
|
||||
* @author Alexander Volz
|
||||
* @author Dennis Maaß
|
||||
* @author Pavel Luhin
|
||||
*/
|
||||
|
||||
class MappingBuilder {
|
||||
@@ -52,7 +56,7 @@ class MappingBuilder {
|
||||
public static final String FIELD_INDEX = "index";
|
||||
public static final String FIELD_FORMAT = "format";
|
||||
public static final String FIELD_SEARCH_ANALYZER = "search_analyzer";
|
||||
public static final String FIELD_INDEX_ANALYZER = "index_analyzer";
|
||||
public static final String FIELD_INDEX_ANALYZER = "analyzer";
|
||||
public static final String FIELD_PROPERTIES = "properties";
|
||||
public static final String FIELD_PARENT = "_parent";
|
||||
|
||||
@@ -65,6 +69,8 @@ class MappingBuilder {
|
||||
public static final String TYPE_VALUE_STRING = "string";
|
||||
public static final String TYPE_VALUE_GEO_POINT = "geo_point";
|
||||
public static final String TYPE_VALUE_COMPLETION = "completion";
|
||||
public static final String TYPE_VALUE_GEO_HASH_PREFIX = "geohash_prefix";
|
||||
public static final String TYPE_VALUE_GEO_HASH_PRECISION = "geohash_precision";
|
||||
|
||||
private static SimpleTypeHolder SIMPLE_TYPE_HOLDER = new SimpleTypeHolder();
|
||||
|
||||
@@ -104,15 +110,26 @@ class MappingBuilder {
|
||||
|
||||
for (java.lang.reflect.Field field : fields) {
|
||||
|
||||
if (field.isAnnotationPresent(Transient.class) || isInIgnoreFields(field)) {
|
||||
if (field.isAnnotationPresent(Transient.class) || isInIgnoreFields(field, fieldAnnotation)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean isGeoField = isGeoField(field);
|
||||
if (field.isAnnotationPresent(Mapping.class)) {
|
||||
String mappingPath = field.getAnnotation(Mapping.class).mappingPath();
|
||||
if (isNotBlank(mappingPath)) {
|
||||
ClassPathResource mappings = new ClassPathResource(mappingPath);
|
||||
if (mappings.exists()) {
|
||||
xContentBuilder.rawField(field.getName(), mappings.getInputStream());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean isGeoPointField = isGeoPointField(field);
|
||||
boolean isCompletionField = isCompletionField(field);
|
||||
|
||||
Field singleField = field.getAnnotation(Field.class);
|
||||
if (!isGeoField && !isCompletionField && isEntity(field) && isAnnotated(field)) {
|
||||
if (!isGeoPointField && !isCompletionField && isEntity(field) && isAnnotated(field)) {
|
||||
if (singleField == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -125,7 +142,7 @@ class MappingBuilder {
|
||||
|
||||
MultiField multiField = field.getAnnotation(MultiField.class);
|
||||
|
||||
if (isGeoField) {
|
||||
if (isGeoPointField) {
|
||||
applyGeoPointFieldMapping(xContentBuilder, field);
|
||||
}
|
||||
|
||||
@@ -137,9 +154,9 @@ class MappingBuilder {
|
||||
if (isRootObject && singleField != null && isIdField(field, idFieldName)) {
|
||||
applyDefaultIdFieldMapping(xContentBuilder, field);
|
||||
} else if (multiField != null) {
|
||||
addMultiFieldMapping(xContentBuilder, field, multiField);
|
||||
addMultiFieldMapping(xContentBuilder, field, multiField, isNestedOrObjectField(field));
|
||||
} else if (singleField != null) {
|
||||
addSingleFieldMapping(xContentBuilder, field, singleField);
|
||||
addSingleFieldMapping(xContentBuilder, field, singleField, isNestedOrObjectField(field));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,13 +181,31 @@ class MappingBuilder {
|
||||
}
|
||||
|
||||
private static boolean isAnnotated(java.lang.reflect.Field field) {
|
||||
return field.getAnnotation(Field.class) != null || field.getAnnotation(MultiField.class) != null || field.getAnnotation(GeoPointField.class) != null || field.getAnnotation(CompletionField.class) != null;
|
||||
return field.getAnnotation(Field.class) != null ||
|
||||
field.getAnnotation(MultiField.class) != null ||
|
||||
field.getAnnotation(GeoPointField.class) != null ||
|
||||
field.getAnnotation(CompletionField.class) != null;
|
||||
}
|
||||
|
||||
private static void applyGeoPointFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field) throws IOException {
|
||||
xContentBuilder.startObject(field.getName());
|
||||
xContentBuilder.field(FIELD_TYPE, TYPE_VALUE_GEO_POINT)
|
||||
.endObject();
|
||||
xContentBuilder.field(FIELD_TYPE, TYPE_VALUE_GEO_POINT);
|
||||
|
||||
GeoPointField annotation = field.getAnnotation(GeoPointField.class);
|
||||
if (annotation != null) {
|
||||
if (annotation.geoHashPrefix()) {
|
||||
xContentBuilder.field(TYPE_VALUE_GEO_HASH_PREFIX, true);
|
||||
if (StringUtils.isNotEmpty(annotation.geoHashPrecision())) {
|
||||
if (NumberUtils.isNumber(annotation.geoHashPrecision())) {
|
||||
xContentBuilder.field(TYPE_VALUE_GEO_HASH_PRECISION, Integer.parseInt(annotation.geoHashPrecision()));
|
||||
} else {
|
||||
xContentBuilder.field(TYPE_VALUE_GEO_HASH_PRECISION, annotation.geoHashPrecision());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xContentBuilder.endObject();
|
||||
}
|
||||
|
||||
private static void applyCompletionFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field, CompletionField annotation) throws IOException {
|
||||
@@ -184,8 +219,8 @@ class MappingBuilder {
|
||||
if (isNotBlank(annotation.searchAnalyzer())) {
|
||||
xContentBuilder.field(FIELD_SEARCH_ANALYZER, annotation.searchAnalyzer());
|
||||
}
|
||||
if (isNotBlank(annotation.indexAnalyzer())) {
|
||||
xContentBuilder.field(FIELD_INDEX_ANALYZER, annotation.indexAnalyzer());
|
||||
if (isNotBlank(annotation.analyzer())) {
|
||||
xContentBuilder.field(FIELD_INDEX_ANALYZER, annotation.analyzer());
|
||||
}
|
||||
}
|
||||
xContentBuilder.endObject();
|
||||
@@ -205,9 +240,11 @@ class MappingBuilder {
|
||||
* @throws IOException
|
||||
*/
|
||||
private static void addSingleFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field,
|
||||
Field fieldAnnotation) throws IOException {
|
||||
Field fieldAnnotation, boolean nestedOrObjectField) throws IOException {
|
||||
xContentBuilder.startObject(field.getName());
|
||||
xContentBuilder.field(FIELD_STORE, fieldAnnotation.store());
|
||||
if(!nestedOrObjectField) {
|
||||
xContentBuilder.field(FIELD_STORE, fieldAnnotation.store());
|
||||
}
|
||||
if (FieldType.Auto != fieldAnnotation.type()) {
|
||||
xContentBuilder.field(FIELD_TYPE, fieldAnnotation.type().name().toLowerCase());
|
||||
if (FieldType.Date == fieldAnnotation.type() && DateFormat.none != fieldAnnotation.format()) {
|
||||
@@ -221,8 +258,8 @@ class MappingBuilder {
|
||||
if (isNotBlank(fieldAnnotation.searchAnalyzer())) {
|
||||
xContentBuilder.field(FIELD_SEARCH_ANALYZER, fieldAnnotation.searchAnalyzer());
|
||||
}
|
||||
if (isNotBlank(fieldAnnotation.indexAnalyzer())) {
|
||||
xContentBuilder.field(FIELD_INDEX_ANALYZER, fieldAnnotation.indexAnalyzer());
|
||||
if (isNotBlank(fieldAnnotation.analyzer())) {
|
||||
xContentBuilder.field(FIELD_INDEX_ANALYZER, fieldAnnotation.analyzer());
|
||||
}
|
||||
xContentBuilder.endObject();
|
||||
}
|
||||
@@ -233,9 +270,9 @@ class MappingBuilder {
|
||||
* @throws IOException
|
||||
*/
|
||||
private static void addNestedFieldMapping(XContentBuilder builder, java.lang.reflect.Field field,
|
||||
NestedField annotation) throws IOException {
|
||||
builder.startObject(field.getName() + "." + annotation.dotSuffix());
|
||||
builder.field(FIELD_STORE, annotation.store());
|
||||
InnerField annotation) throws IOException {
|
||||
builder.startObject(annotation.suffix());
|
||||
//builder.field(FIELD_STORE, annotation.store());
|
||||
if (FieldType.Auto != annotation.type()) {
|
||||
builder.field(FIELD_TYPE, annotation.type().name().toLowerCase());
|
||||
}
|
||||
@@ -257,46 +294,19 @@ class MappingBuilder {
|
||||
* @throws IOException
|
||||
*/
|
||||
private static void addMultiFieldMapping(XContentBuilder builder, java.lang.reflect.Field field,
|
||||
MultiField annotation) throws IOException {
|
||||
MultiField annotation, boolean nestedOrObjectField) throws IOException {
|
||||
builder.startObject(field.getName());
|
||||
builder.field(FIELD_TYPE, "multi_field");
|
||||
builder.startObject("fields");
|
||||
//add standard field
|
||||
addSingleFieldMapping(builder, field, annotation.mainField());
|
||||
for (NestedField nestedField : annotation.otherFields()) {
|
||||
addNestedFieldMapping(builder, field, nestedField);
|
||||
addSingleFieldMapping(builder, field, annotation.mainField(),nestedOrObjectField);
|
||||
for (InnerField innerField : annotation.otherFields()) {
|
||||
addNestedFieldMapping(builder, field, innerField);
|
||||
}
|
||||
builder.endObject();
|
||||
builder.endObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Facet field for string type, for other types we don't need it(long, int, double, float)
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private static void addFacetMapping(XContentBuilder builder, java.lang.reflect.Field field, Field annotation) throws IOException {
|
||||
builder.startObject(FacetRequest.FIELD_UNTOUCHED)
|
||||
.field(FIELD_TYPE, TYPE_VALUE_STRING)
|
||||
.field(FIELD_INDEX, INDEX_VALUE_NOT_ANALYZED)
|
||||
.field(FIELD_STORE, true);
|
||||
builder.endObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort field for string type, for other types we don't need it(long, int, double, float)
|
||||
* value of the field should be converted to lowercase and not analise
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private static void addSortMapping(XContentBuilder builder, java.lang.reflect.Field field, Field annotation) throws IOException {
|
||||
builder.startObject(FacetRequest.FIELD_SORT)
|
||||
.field(FIELD_TYPE, TYPE_VALUE_STRING)
|
||||
.field(FIELD_INDEX, "keyword")
|
||||
.field(FIELD_STORE, true);
|
||||
builder.endObject();
|
||||
}
|
||||
|
||||
protected static boolean isEntity(java.lang.reflect.Field field) {
|
||||
TypeInformation typeInformation = ClassTypeInformation.from(field.getType());
|
||||
Class<?> clazz = getFieldType(field);
|
||||
@@ -328,10 +338,9 @@ class MappingBuilder {
|
||||
return idFieldName.equals(field.getName());
|
||||
}
|
||||
|
||||
private static boolean isInIgnoreFields(java.lang.reflect.Field field) {
|
||||
Field fieldAnnotation = field.getAnnotation(Field.class);
|
||||
if (null != fieldAnnotation) {
|
||||
String[] ignoreFields = fieldAnnotation.ignoreFields();
|
||||
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;
|
||||
@@ -342,7 +351,7 @@ class MappingBuilder {
|
||||
return fieldAnnotation != null && (FieldType.Nested == fieldAnnotation.type() || FieldType.Object == fieldAnnotation.type());
|
||||
}
|
||||
|
||||
private static boolean isGeoField(java.lang.reflect.Field field) {
|
||||
private static boolean isGeoPointField(java.lang.reflect.Field field) {
|
||||
return field.getType() == GeoPoint.class || field.getAnnotation(GeoPointField.class) != null;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,11 +17,13 @@ package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
|
||||
|
||||
/**
|
||||
* @author Artur Konczak
|
||||
* @author Petar Tahchiev
|
||||
*/
|
||||
public interface SearchResultMapper {
|
||||
|
||||
<T> FacetedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable);
|
||||
<T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable);
|
||||
}
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author Petar Tahchiev
|
||||
*/
|
||||
public interface AggregatedPage<T> extends FacetedPage<T> {
|
||||
|
||||
boolean hasAggregations();
|
||||
|
||||
Aggregations getAggregations();
|
||||
|
||||
Aggregation getAggregation(String name);
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
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;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.elasticsearch.core.FacetedPageImpl;
|
||||
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
|
||||
|
||||
/**
|
||||
* @author Petar Tahchiev
|
||||
* @author Artur Konczak
|
||||
* @author Mohsin Husen
|
||||
*/
|
||||
public class AggregatedPageImpl<T> extends FacetedPageImpl<T> implements AggregatedPage<T> {
|
||||
|
||||
private Aggregations aggregations;
|
||||
private Map<String, Aggregation> mapOfAggregations = new HashMap<String, Aggregation>();
|
||||
|
||||
public AggregatedPageImpl(List<T> content) {
|
||||
super(content);
|
||||
}
|
||||
|
||||
public AggregatedPageImpl(List<T> content, Pageable pageable, long total) {
|
||||
super(content, pageable, total);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAggregations() {
|
||||
return aggregations != null && mapOfAggregations.size() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Aggregations getAggregations() {
|
||||
return aggregations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Aggregation getAggregation(String name) {
|
||||
return aggregations == null ? null : aggregations.get(name);
|
||||
}
|
||||
}
|
||||
+5
-3
@@ -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.
|
||||
@@ -31,8 +31,8 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
|
||||
public class MappingElasticsearchConverter implements ElasticsearchConverter, ApplicationContextAware {
|
||||
|
||||
private final MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext;
|
||||
@@ -43,7 +43,9 @@ public class MappingElasticsearchConverter implements ElasticsearchConverter, Ap
|
||||
|
||||
public MappingElasticsearchConverter(
|
||||
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext) {
|
||||
Assert.notNull(mappingContext);
|
||||
|
||||
Assert.notNull(mappingContext, "MappingContext must not be null!");
|
||||
|
||||
this.mappingContext = mappingContext;
|
||||
this.conversionService = new DefaultConversionService();
|
||||
}
|
||||
|
||||
+6
-1
@@ -13,15 +13,20 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.elasticsearch.core.facet;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* @author Artur Konczak
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class AbstractFacetRequest implements FacetRequest {
|
||||
|
||||
public static final String INTERNAL_STATS = "internal-stats";
|
||||
|
||||
private String name;
|
||||
private boolean applyQueryFilter;
|
||||
|
||||
@@ -42,4 +47,4 @@ public abstract class AbstractFacetRequest implements FacetRequest {
|
||||
public boolean applyQueryFilter() {
|
||||
return applyQueryFilter;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -23,6 +23,7 @@ import org.springframework.util.Assert;
|
||||
* @author Artur Konczak
|
||||
* @author Jonathan Yan
|
||||
*/
|
||||
@Deprecated
|
||||
public class AbstractFacetResult implements FacetResult {
|
||||
|
||||
private final String name;
|
||||
|
||||
-81
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core.facet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.elasticsearch.search.facet.Facet;
|
||||
import org.elasticsearch.search.facet.histogram.HistogramFacet;
|
||||
import org.elasticsearch.search.facet.range.RangeFacet;
|
||||
import org.elasticsearch.search.facet.statistical.StatisticalFacet;
|
||||
import org.elasticsearch.search.facet.terms.TermsFacet;
|
||||
import org.springframework.data.elasticsearch.core.facet.result.*;
|
||||
|
||||
/**
|
||||
* @author Artur Konczak
|
||||
* @author Petar Tahchiev
|
||||
*/
|
||||
public class DefaultFacetMapper {
|
||||
|
||||
public static FacetResult parse(Facet facet) {
|
||||
if (facet instanceof TermsFacet) {
|
||||
return parseTerm((TermsFacet) facet);
|
||||
}
|
||||
|
||||
if (facet instanceof RangeFacet) {
|
||||
return parseRange((RangeFacet) facet);
|
||||
}
|
||||
|
||||
if (facet instanceof StatisticalFacet) {
|
||||
return parseStatistical((StatisticalFacet) facet);
|
||||
}
|
||||
|
||||
if (facet instanceof HistogramFacet) {
|
||||
return parseHistogram((HistogramFacet) facet);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static FacetResult parseTerm(TermsFacet facet) {
|
||||
List<Term> entries = new ArrayList<Term>();
|
||||
for (TermsFacet.Entry entry : facet.getEntries()) {
|
||||
entries.add(new Term(entry.getTerm().toString(), entry.getCount()));
|
||||
}
|
||||
return new TermResult(facet.getName(), entries);
|
||||
}
|
||||
|
||||
private static FacetResult parseRange(RangeFacet facet) {
|
||||
List<Range> entries = new ArrayList<Range>();
|
||||
for (RangeFacet.Entry entry : facet.getEntries()) {
|
||||
entries.add(new Range(entry.getFrom() == Double.NEGATIVE_INFINITY ? null : entry.getFrom(), entry.getTo() == Double.POSITIVE_INFINITY ? null : entry.getTo(), entry.getCount(), entry.getTotal(), entry.getTotalCount(), entry.getMin(), entry.getMax()));
|
||||
}
|
||||
return new RangeResult(facet.getName(), entries);
|
||||
}
|
||||
|
||||
private static FacetResult parseStatistical(StatisticalFacet facet) {
|
||||
return new StatisticalResult(facet.getName(), facet.getCount(), facet.getMax(), facet.getMin(), facet.getMean(), facet.getStdDeviation(), facet.getSumOfSquares(), facet.getTotal(), facet.getVariance());
|
||||
}
|
||||
|
||||
private static FacetResult parseHistogram(HistogramFacet facet) {
|
||||
List<IntervalUnit> entries = new ArrayList<IntervalUnit>();
|
||||
for (HistogramFacet.Entry entry : facet.getEntries()) {
|
||||
entries.add(new IntervalUnit(entry.getKey(), entry.getCount(), entry.getTotalCount(), entry.getTotal(), entry.getMean(), entry.getMin(), entry.getMax()));
|
||||
}
|
||||
return new HistogramResult(facet.getName(), entries);
|
||||
}
|
||||
}
|
||||
@@ -13,19 +13,21 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.elasticsearch.core.facet;
|
||||
|
||||
import org.elasticsearch.search.facet.FacetBuilder;
|
||||
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
||||
|
||||
/**
|
||||
* @author Artur Koczak
|
||||
*/
|
||||
@Deprecated
|
||||
public interface FacetRequest {
|
||||
|
||||
public static final String FIELD_UNTOUCHED = "untouched";
|
||||
public static final String FIELD_SORT = "sort";
|
||||
|
||||
FacetBuilder getFacet();
|
||||
AbstractAggregationBuilder getFacet();
|
||||
|
||||
boolean applyQueryFilter();
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ package org.springframework.data.elasticsearch.core.facet;
|
||||
* @author Artur Konczak
|
||||
* @author Jonathan Yan
|
||||
*/
|
||||
@Deprecated
|
||||
public interface FacetResult {
|
||||
|
||||
String getName();
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.springframework.data.elasticsearch.core.facet;
|
||||
* @author Artur Konczak
|
||||
* @author Petar Tahchiev
|
||||
*/
|
||||
@Deprecated
|
||||
public enum FacetType {
|
||||
|
||||
term, range, histogram, statistical
|
||||
|
||||
+18
-14
@@ -13,26 +13,28 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.elasticsearch.core.facet.request;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.elasticsearch.search.facet.FacetBuilder;
|
||||
import org.elasticsearch.search.facet.FacetBuilders;
|
||||
import org.elasticsearch.search.facet.histogram.HistogramFacetBuilder;
|
||||
import org.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.DateHistogramInterval;
|
||||
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* @author Artur Konczak
|
||||
* @author Mohsin Husen
|
||||
*/
|
||||
@Deprecated
|
||||
public class HistogramFacetRequest extends AbstractFacetRequest {
|
||||
|
||||
private String field;
|
||||
private long interval;
|
||||
private TimeUnit timeUnit;
|
||||
private DateHistogramInterval timeUnit;
|
||||
|
||||
public HistogramFacetRequest(String name) {
|
||||
super(name);
|
||||
@@ -46,24 +48,26 @@ public class HistogramFacetRequest extends AbstractFacetRequest {
|
||||
this.interval = interval;
|
||||
}
|
||||
|
||||
public void setTimeUnit(TimeUnit timeUnit) {
|
||||
public void setTimeUnit(DateHistogramInterval timeUnit) {
|
||||
this.timeUnit = timeUnit;
|
||||
}
|
||||
|
||||
public FacetBuilder getFacet() {
|
||||
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(interval > 0, "Please provide interval as positive value greater them zero !!!");
|
||||
|
||||
HistogramFacetBuilder builder = FacetBuilders.histogramFacet(getName());
|
||||
builder.field(field);
|
||||
DateHistogramBuilder dateHistogramBuilder = AggregationBuilders.dateHistogram(getName());
|
||||
dateHistogramBuilder.field(field);
|
||||
|
||||
if (timeUnit != null) {
|
||||
builder.interval(interval, timeUnit);
|
||||
dateHistogramBuilder.interval(timeUnit);
|
||||
} else {
|
||||
builder.interval(interval);
|
||||
dateHistogramBuilder.interval(interval);
|
||||
}
|
||||
|
||||
return builder;
|
||||
dateHistogramBuilder.subAggregation(AggregationBuilders.extendedStats(INTERNAL_STATS));
|
||||
|
||||
return dateHistogramBuilder;
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-4
@@ -13,15 +13,17 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.elasticsearch.core.facet.request;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
|
||||
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
|
||||
|
||||
|
||||
/**
|
||||
* @author Artur Konczak
|
||||
*/
|
||||
@Deprecated
|
||||
public class HistogramFacetRequestBuilder {
|
||||
|
||||
HistogramFacetRequest result;
|
||||
@@ -40,7 +42,7 @@ public class HistogramFacetRequestBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public HistogramFacetRequestBuilder timeUnit(TimeUnit timeUnit) {
|
||||
public HistogramFacetRequestBuilder timeUnit(DateHistogramInterval timeUnit) {
|
||||
result.setTimeUnit(timeUnit);
|
||||
return this;
|
||||
}
|
||||
@@ -53,4 +55,4 @@ public class HistogramFacetRequestBuilder {
|
||||
result.setApplyQueryFilter(true);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
-14
@@ -13,36 +13,31 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.elasticsearch.core.facet.request;
|
||||
|
||||
import org.elasticsearch.search.facet.FacetBuilder;
|
||||
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
||||
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
|
||||
|
||||
|
||||
/**
|
||||
* @author Artur Konczak
|
||||
* @author Mohsin Husen
|
||||
*/
|
||||
@Deprecated
|
||||
public class NativeFacetRequest implements FacetRequest {
|
||||
|
||||
private FacetBuilder facet;
|
||||
private boolean applyQueryFilter;
|
||||
|
||||
public NativeFacetRequest(FacetBuilder facet) {
|
||||
this(facet, false);
|
||||
}
|
||||
|
||||
public NativeFacetRequest(FacetBuilder facet, boolean applyQueryFilter) {
|
||||
this.facet = facet;
|
||||
this.applyQueryFilter = applyQueryFilter;
|
||||
public NativeFacetRequest() {
|
||||
throw new UnsupportedOperationException("Native Facet are not supported in Elasticsearch 2.x - use Aggregation");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FacetBuilder getFacet() {
|
||||
return facet;
|
||||
public AbstractAggregationBuilder getFacet() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyQueryFilter() {
|
||||
return applyQueryFilter;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+21
-21
@@ -13,26 +13,30 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.elasticsearch.core.facet.request;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.elasticsearch.search.facet.FacetBuilder;
|
||||
import org.elasticsearch.search.facet.FacetBuilders;
|
||||
import org.elasticsearch.search.facet.range.RangeFacetBuilder;
|
||||
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
||||
import org.elasticsearch.search.aggregations.AggregationBuilders;
|
||||
import org.elasticsearch.search.aggregations.bucket.range.RangeBuilder;
|
||||
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Range facet for numeric fields
|
||||
*
|
||||
* @author Artur Konczak
|
||||
* @author Akos Bordas
|
||||
*/
|
||||
@Deprecated
|
||||
public class RangeFacetRequest extends AbstractFacetRequest {
|
||||
|
||||
public static final String RANGE_INTERNAL_SUM = "range-internal-sum";
|
||||
private String field;
|
||||
private String keyField;
|
||||
private String valueField;
|
||||
@@ -57,7 +61,7 @@ public class RangeFacetRequest extends AbstractFacetRequest {
|
||||
}
|
||||
|
||||
public void range(String from, String to) {
|
||||
entries.add(new StringEntry(from, to));
|
||||
throw new UnsupportedOperationException("Native Facet are not supported in Elasticsearch 2.x - use Aggregation");
|
||||
}
|
||||
|
||||
public void addRange(Double from, Double to) {
|
||||
@@ -65,32 +69,27 @@ public class RangeFacetRequest extends AbstractFacetRequest {
|
||||
}
|
||||
|
||||
public void addRange(String from, String to) {
|
||||
entries.add(new StringEntry(from, to));
|
||||
throw new UnsupportedOperationException("Native Facet are not supported in Elasticsearch 2.x - use Aggregation");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FacetBuilder getFacet() {
|
||||
public AbstractAggregationBuilder getFacet() {
|
||||
Assert.notNull(getName(), "Facet name can't be a null !!!");
|
||||
Assert.isTrue(StringUtils.isNotBlank(field) || StringUtils.isNotBlank(keyField) && StringUtils.isNotBlank(valueField), "Please select field or key field and value field !!!");
|
||||
|
||||
RangeFacetBuilder builder = FacetBuilders.rangeFacet(getName());
|
||||
if (StringUtils.isNotBlank(keyField)) {
|
||||
builder.keyField(keyField).valueField(valueField);
|
||||
} else {
|
||||
builder.field(field);
|
||||
}
|
||||
RangeBuilder rangeBuilder = AggregationBuilders.range(getName());
|
||||
rangeBuilder.field(StringUtils.isNotBlank(keyField) ? keyField : field );
|
||||
|
||||
for (Entry entry : entries) {
|
||||
if (entry instanceof DoubleEntry) {
|
||||
DoubleEntry doubleEntry = (DoubleEntry) entry;
|
||||
builder.addRange(validateValue(doubleEntry.getFrom(), Double.NEGATIVE_INFINITY), validateValue(doubleEntry.getTo(), Double.POSITIVE_INFINITY));
|
||||
} else {
|
||||
StringEntry stringEntry = (StringEntry) entry;
|
||||
builder.addRange(stringEntry.getFrom(), stringEntry.getTo());
|
||||
}
|
||||
DoubleEntry doubleEntry = (DoubleEntry) entry;
|
||||
rangeBuilder.addRange(validateValue(doubleEntry.getFrom(), Double.NEGATIVE_INFINITY), validateValue(doubleEntry.getTo(), Double.POSITIVE_INFINITY));
|
||||
}
|
||||
|
||||
return builder;
|
||||
rangeBuilder.subAggregation(AggregationBuilders.extendedStats(INTERNAL_STATS));
|
||||
if(StringUtils.isNotBlank(valueField)){
|
||||
rangeBuilder.subAggregation(AggregationBuilders.sum(RANGE_INTERNAL_SUM).field(valueField));
|
||||
}
|
||||
|
||||
return rangeBuilder;
|
||||
}
|
||||
|
||||
private double validateValue(Double value, double defaultValue) {
|
||||
@@ -130,3 +129,4 @@ public class RangeFacetRequest extends AbstractFacetRequest {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -13,15 +13,18 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.elasticsearch.core.facet.request;
|
||||
|
||||
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
|
||||
|
||||
|
||||
/**
|
||||
* Basic range facet
|
||||
*
|
||||
* @author Artur Konczak
|
||||
*/
|
||||
@Deprecated
|
||||
public class RangeFacetRequestBuilder {
|
||||
|
||||
RangeFacetRequest result;
|
||||
@@ -79,4 +82,4 @@ public class RangeFacetRequestBuilder {
|
||||
public FacetRequest build() {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
-16
@@ -13,19 +13,20 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.elasticsearch.core.facet.request;
|
||||
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.elasticsearch.search.facet.FacetBuilder;
|
||||
import org.elasticsearch.search.facet.FacetBuilders;
|
||||
import org.elasticsearch.search.facet.statistical.StatisticalFacetBuilder;
|
||||
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
||||
import org.elasticsearch.search.aggregations.AggregationBuilders;
|
||||
import org.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* @author Petar Tahchiev
|
||||
*/
|
||||
@Deprecated
|
||||
public class StatisticalFacetRequest extends AbstractFacetRequest {
|
||||
|
||||
private String field;
|
||||
@@ -41,20 +42,12 @@ public class StatisticalFacetRequest extends AbstractFacetRequest {
|
||||
}
|
||||
|
||||
public void setFields(String... fields) {
|
||||
this.fields = fields;
|
||||
throw new UnsupportedOperationException("Native Facet are not supported in Elasticsearch 2.x - use Aggregation");
|
||||
}
|
||||
|
||||
public FacetBuilder getFacet() {
|
||||
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 !!!");
|
||||
|
||||
StatisticalFacetBuilder builder = FacetBuilders.statisticalFacet(getName());
|
||||
if (ArrayUtils.isNotEmpty(fields)) {
|
||||
builder.fields(fields);
|
||||
} else {
|
||||
builder.field(field);
|
||||
}
|
||||
|
||||
return builder;
|
||||
return AggregationBuilders.extendedStats(getName()).field(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-1
@@ -13,13 +13,16 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.elasticsearch.core.facet.request;
|
||||
|
||||
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
|
||||
|
||||
|
||||
/**
|
||||
* @author Petar Tahchiev
|
||||
*/
|
||||
@Deprecated
|
||||
public class StatisticalFacetRequestBuilder {
|
||||
|
||||
StatisticalFacetRequest result;
|
||||
@@ -46,4 +49,4 @@ public class StatisticalFacetRequestBuilder {
|
||||
public FacetRequest build() {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -19,6 +19,7 @@ package org.springframework.data.elasticsearch.core.facet.request;
|
||||
* @author Artur Konczak
|
||||
* @author Mohsin Husen
|
||||
*/
|
||||
@Deprecated
|
||||
public enum TermFacetOrder {
|
||||
|
||||
ascTerm, descTerm, ascCount, descCount;
|
||||
|
||||
+24
-25
@@ -13,37 +13,41 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.elasticsearch.core.facet.request;
|
||||
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.elasticsearch.search.facet.FacetBuilder;
|
||||
import org.elasticsearch.search.facet.FacetBuilders;
|
||||
import org.elasticsearch.search.facet.terms.TermsFacet;
|
||||
import org.elasticsearch.search.facet.terms.TermsFacetBuilder;
|
||||
import org.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.springframework.data.elasticsearch.core.facet.AbstractFacetRequest;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Term facet
|
||||
*
|
||||
* @author Artur Konczak
|
||||
*/
|
||||
@Deprecated
|
||||
public class TermFacetRequest extends AbstractFacetRequest {
|
||||
|
||||
private String[] fields;
|
||||
private Object[] excludeTerms;
|
||||
private String[] excludeTerms;
|
||||
private int size = 10;
|
||||
private TermFacetOrder order = TermFacetOrder.descCount;
|
||||
private boolean allTerms = false;
|
||||
private String regex = null;
|
||||
private int regexFlag = 0;
|
||||
|
||||
public TermFacetRequest(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public void setFields(String... fields) {
|
||||
Assert.isTrue(ArrayUtils.isNotEmpty(fields), "Term agg need one field only");
|
||||
Assert.isTrue(ArrayUtils.getLength(fields) == 1, "Term agg need one field only");
|
||||
this.fields = fields;
|
||||
}
|
||||
|
||||
@@ -56,7 +60,7 @@ public class TermFacetRequest extends AbstractFacetRequest {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
public void setExcludeTerms(Object... excludeTerms) {
|
||||
public void setExcludeTerms(String... excludeTerms) {
|
||||
this.excludeTerms = excludeTerms;
|
||||
}
|
||||
|
||||
@@ -68,41 +72,36 @@ public class TermFacetRequest extends AbstractFacetRequest {
|
||||
this.regex = regex;
|
||||
}
|
||||
|
||||
public void setRegex(String regex, int regexFlag) {
|
||||
this.regex = regex;
|
||||
this.regexFlag = regexFlag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FacetBuilder getFacet() {
|
||||
public AbstractAggregationBuilder getFacet() {
|
||||
Assert.notEmpty(fields, "Please select at last one field !!!");
|
||||
TermsFacetBuilder builder = FacetBuilders.termsFacet(getName()).fields(fields).size(size);
|
||||
switch (order) {
|
||||
TermsBuilder termsBuilder = AggregationBuilders.terms(getName()).field(fields[0]).size(this.size);
|
||||
|
||||
switch (order) {
|
||||
case descTerm:
|
||||
builder.order(TermsFacet.ComparatorType.REVERSE_TERM);
|
||||
termsBuilder.order(Terms.Order.term(false));
|
||||
break;
|
||||
case ascTerm:
|
||||
builder.order(TermsFacet.ComparatorType.TERM);
|
||||
termsBuilder.order(Terms.Order.term(true));
|
||||
break;
|
||||
case ascCount:
|
||||
builder.order(TermsFacet.ComparatorType.REVERSE_COUNT);
|
||||
case descCount:
|
||||
termsBuilder.order(Terms.Order.count(false));
|
||||
break;
|
||||
default:
|
||||
builder.order(TermsFacet.ComparatorType.COUNT);
|
||||
termsBuilder.order(Terms.Order.count(true));
|
||||
}
|
||||
if (ArrayUtils.isNotEmpty(excludeTerms)) {
|
||||
builder.exclude(excludeTerms);
|
||||
termsBuilder.exclude(excludeTerms);
|
||||
}
|
||||
|
||||
if (allTerms) {
|
||||
builder.allTerms(allTerms);
|
||||
termsBuilder.size(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(regex)) {
|
||||
builder.regex(regex, regexFlag);
|
||||
termsBuilder.include(regex);
|
||||
}
|
||||
|
||||
return builder;
|
||||
return termsBuilder;
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-7
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.elasticsearch.core.facet.request;
|
||||
|
||||
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
|
||||
@@ -22,6 +23,7 @@ import org.springframework.data.elasticsearch.core.facet.FacetRequest;
|
||||
*
|
||||
* @author Artur Konczak
|
||||
*/
|
||||
@Deprecated
|
||||
public class TermFacetRequestBuilder {
|
||||
|
||||
private TermFacetRequest result;
|
||||
@@ -40,7 +42,7 @@ public class TermFacetRequestBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public TermFacetRequestBuilder excludeTerms(Object... terms) {
|
||||
public TermFacetRequestBuilder excludeTerms(String... terms) {
|
||||
result.setExcludeTerms(terms);
|
||||
return this;
|
||||
}
|
||||
@@ -55,11 +57,6 @@ public class TermFacetRequestBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public TermFacetRequestBuilder regex(String regex, int regexFlag) {
|
||||
result.setRegex(regex, regexFlag);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TermFacetRequestBuilder ascTerm() {
|
||||
result.setOrder(TermFacetOrder.ascTerm);
|
||||
return this;
|
||||
@@ -88,4 +85,4 @@ public class TermFacetRequestBuilder {
|
||||
public FacetRequest build() {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -23,6 +23,7 @@ import org.springframework.data.elasticsearch.core.facet.FacetType;
|
||||
/**
|
||||
* @author Artur Konczak
|
||||
*/
|
||||
@Deprecated
|
||||
public class HistogramResult extends AbstractFacetResult {
|
||||
|
||||
private List<IntervalUnit> terms;
|
||||
|
||||
+1
@@ -26,6 +26,7 @@ import java.util.Date;
|
||||
* @author Artur Konczak
|
||||
* @author Jonathan Yan
|
||||
*/
|
||||
@Deprecated
|
||||
public class IntervalUnit {
|
||||
|
||||
private static final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||
|
||||
@@ -23,6 +23,7 @@ package org.springframework.data.elasticsearch.core.facet.result;
|
||||
* @author Artur Konczak
|
||||
* @author Jonathan Yan
|
||||
*/
|
||||
@Deprecated
|
||||
public class Range {
|
||||
|
||||
private Double from;
|
||||
|
||||
+1
@@ -28,6 +28,7 @@ import org.springframework.data.elasticsearch.core.facet.FacetType;
|
||||
* @author Artur Konczak
|
||||
* @author Jonathan Yan
|
||||
*/
|
||||
@Deprecated
|
||||
public class RangeResult extends AbstractFacetResult {
|
||||
|
||||
private List<Range> ranges;
|
||||
|
||||
+1
@@ -21,6 +21,7 @@ import org.springframework.data.elasticsearch.core.facet.FacetType;
|
||||
/**
|
||||
* @author Petar Tahchiev
|
||||
*/
|
||||
@Deprecated
|
||||
public class StatisticalResult extends AbstractFacetResult {
|
||||
|
||||
private long count;
|
||||
|
||||
@@ -23,12 +23,13 @@ package org.springframework.data.elasticsearch.core.facet.result;
|
||||
* @author Artur Konczak
|
||||
* @author Jonathan Yan
|
||||
*/
|
||||
@Deprecated
|
||||
public class Term {
|
||||
|
||||
private String term;
|
||||
private int count;
|
||||
private long count;
|
||||
|
||||
public Term(String term, int count) {
|
||||
public Term(String term, long count) {
|
||||
this.term = term;
|
||||
this.count = count;
|
||||
}
|
||||
@@ -37,7 +38,7 @@ public class Term {
|
||||
return term;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
public long getCount() {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
+21
-1
@@ -27,17 +27,37 @@ import org.springframework.data.elasticsearch.core.facet.FacetType;
|
||||
* @author Mohsin Husen
|
||||
* @author Artur Konczak
|
||||
* @author Jonathan Yan
|
||||
* @author Matija Obreza
|
||||
*/
|
||||
@Deprecated
|
||||
public class TermResult extends AbstractFacetResult {
|
||||
|
||||
private List<Term> terms;
|
||||
private long total;
|
||||
private long other;
|
||||
private long missing;
|
||||
|
||||
public TermResult(String name, List<Term> terms) {
|
||||
public TermResult(String name, List<Term> terms, long total, long other, long missing) {
|
||||
super(name, FacetType.term);
|
||||
this.terms = terms;
|
||||
this.total = total;
|
||||
this.other = other;
|
||||
this.missing = missing;
|
||||
}
|
||||
|
||||
public List<Term> getTerms() {
|
||||
return terms;
|
||||
}
|
||||
|
||||
public long getTotal() {
|
||||
return total;
|
||||
}
|
||||
|
||||
public long getOther() {
|
||||
return other;
|
||||
}
|
||||
|
||||
public long getMissing() {
|
||||
return missing;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package org.springframework.data.elasticsearch.core.geo;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.Version;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import org.springframework.data.geo.Point;
|
||||
|
||||
/**
|
||||
* @author Artur Konaczak
|
||||
*/
|
||||
public class CustomGeoModule extends SimpleModule {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Creates a new {@link org.springframework.data.elasticsearch.core.geo.CustomGeoModule} registering serializers and deserializers for spring data commons geo-spatial types.
|
||||
*/
|
||||
public CustomGeoModule() {
|
||||
|
||||
super("Spring Data Elasticsearch Geo", new Version(1, 0, 0, null, "org.springframework.data.elasticsearch", "spring-data-elasticsearch-geo"));
|
||||
addSerializer(Point.class, new PointSerializer());
|
||||
addDeserializer(Point.class, new PointDeserializer());
|
||||
}
|
||||
}
|
||||
|
||||
class PointSerializer extends JsonSerializer<Point> {
|
||||
|
||||
@Override
|
||||
public void serialize(Point value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
|
||||
gen.writeObject(GeoPoint.fromPoint(value));
|
||||
// gen.writeStartObject();
|
||||
// gen.writeNumberField("lat", value.getY());
|
||||
// gen.writeNumberField("lon", value.getX());
|
||||
// gen.writeEndObject();
|
||||
}
|
||||
}
|
||||
|
||||
class PointDeserializer extends JsonDeserializer<Point> {
|
||||
|
||||
@Override
|
||||
public Point deserialize(JsonParser p, DeserializationContext context) throws IOException, JsonProcessingException {
|
||||
|
||||
GeoPoint point = p.readValueAs(GeoPoint.class);
|
||||
// Double lat = null;
|
||||
// Double lon = null;
|
||||
// //skipp field name
|
||||
// p.nextFieldName();
|
||||
// if ("lat".equals(p.getCurrentName())) {
|
||||
// //get value
|
||||
// p.nextFieldName();
|
||||
// lat = p.getDoubleValue();
|
||||
// p.nextFieldName();
|
||||
// }
|
||||
// if ("lon".equals(p.getCurrentName())) {
|
||||
// //get value
|
||||
// p.nextFieldName();
|
||||
// lon = p.getDoubleValue();
|
||||
// }
|
||||
// return new Point(lon, lat);
|
||||
return GeoPoint.toPoint(point);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,6 +21,7 @@ import org.springframework.data.geo.Point;
|
||||
* geo-location used for #{@link org.springframework.data.elasticsearch.core.query.Criteria}.
|
||||
*
|
||||
* @author Franck Marchand
|
||||
* @author Mohsin Husen
|
||||
*/
|
||||
public class GeoPoint {
|
||||
|
||||
@@ -51,7 +52,11 @@ public class GeoPoint {
|
||||
* @return a {@link org.springframework.data.elasticsearch.core.geo.GeoPoint}
|
||||
*/
|
||||
public static GeoPoint fromPoint(Point point) {
|
||||
return new GeoPoint(point.getY(), point.getX());
|
||||
return new GeoPoint(point.getX(), point.getY());
|
||||
}
|
||||
|
||||
public static Point toPoint(GeoPoint point) {
|
||||
return new Point(point.getLat(), point.getLon());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
@@ -34,6 +34,8 @@ public interface ElasticsearchPersistentEntity<T> extends PersistentEntity<T, El
|
||||
|
||||
short getReplicas();
|
||||
|
||||
boolean isUseServerConfiguration();
|
||||
|
||||
String getRefreshInterval();
|
||||
|
||||
String getIndexStoreType();
|
||||
@@ -45,4 +47,6 @@ public interface ElasticsearchPersistentEntity<T> extends PersistentEntity<T, El
|
||||
ElasticsearchPersistentProperty getParentIdProperty();
|
||||
|
||||
String settingPath();
|
||||
|
||||
boolean isCreateIndexAndMapping();
|
||||
}
|
||||
|
||||
+19
-5
@@ -50,6 +50,7 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
|
||||
|
||||
private String indexName;
|
||||
private String indexType;
|
||||
private boolean useServerConfiguration;
|
||||
private short shards;
|
||||
private short replicas;
|
||||
private String refreshInterval;
|
||||
@@ -57,6 +58,7 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
|
||||
private String parentType;
|
||||
private ElasticsearchPersistentProperty parentIdProperty;
|
||||
private String settingPath;
|
||||
private boolean createIndexAndMapping;
|
||||
|
||||
public SimpleElasticsearchPersistentEntity(TypeInformation<T> typeInformation) {
|
||||
super(typeInformation);
|
||||
@@ -68,12 +70,14 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
|
||||
Document document = clazz.getAnnotation(Document.class);
|
||||
Assert.hasText(document.indexName(),
|
||||
" Unknown indexName. Make sure the indexName is defined. e.g @Document(indexName=\"foo\")");
|
||||
this.indexName = typeInformation.getType().getAnnotation(Document.class).indexName();
|
||||
this.indexName = document.indexName();
|
||||
this.indexType = hasText(document.type()) ? document.type() : clazz.getSimpleName().toLowerCase(Locale.ENGLISH);
|
||||
this.shards = typeInformation.getType().getAnnotation(Document.class).shards();
|
||||
this.replicas = typeInformation.getType().getAnnotation(Document.class).replicas();
|
||||
this.refreshInterval = typeInformation.getType().getAnnotation(Document.class).refreshInterval();
|
||||
this.indexStoreType = typeInformation.getType().getAnnotation(Document.class).indexStoreType();
|
||||
this.useServerConfiguration = document.useServerConfiguration();
|
||||
this.shards = document.shards();
|
||||
this.replicas = document.replicas();
|
||||
this.refreshInterval = document.refreshInterval();
|
||||
this.indexStoreType = document.indexStoreType();
|
||||
this.createIndexAndMapping = document.createIndex();
|
||||
}
|
||||
if (clazz.isAnnotationPresent(Setting.class)) {
|
||||
this.settingPath = typeInformation.getType().getAnnotation(Setting.class).settingPath();
|
||||
@@ -114,6 +118,11 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
|
||||
return replicas;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUseServerConfiguration() {
|
||||
return useServerConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRefreshInterval() {
|
||||
return refreshInterval;
|
||||
@@ -134,6 +143,11 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
|
||||
return settingPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCreateIndexAndMapping() {
|
||||
return createIndexAndMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPersistentProperty(ElasticsearchPersistentProperty property) {
|
||||
super.addPersistentProperty(property);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-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,12 +15,10 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core.query;
|
||||
|
||||
import static org.apache.commons.collections.CollectionUtils.*;
|
||||
|
||||
import static java.util.Collections.addAll;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.elasticsearch.action.search.SearchType;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
@@ -31,6 +29,7 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
abstract class AbstractQuery implements Query {
|
||||
|
||||
@@ -39,6 +38,7 @@ abstract class AbstractQuery implements Query {
|
||||
protected List<String> indices = new ArrayList<String>();
|
||||
protected List<String> types = new ArrayList<String>();
|
||||
protected List<String> fields = new ArrayList<String>();
|
||||
protected SourceFilter sourceFilter;
|
||||
protected float minScore;
|
||||
protected Collection<String> ids;
|
||||
protected String route;
|
||||
@@ -56,7 +56,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());
|
||||
}
|
||||
@@ -91,6 +93,16 @@ abstract class AbstractQuery implements Query {
|
||||
return types;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSourceFilter(SourceFilter sourceFilter) {
|
||||
this.sourceFilter = sourceFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceFilter getSourceFilter() {
|
||||
return sourceFilter;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public final <T extends Query> T addSort(Sort sort) {
|
||||
if (sort == null) {
|
||||
|
||||
@@ -17,7 +17,7 @@ package org.springframework.data.elasticsearch.core.query;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.elasticsearch.index.query.FilterBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
|
||||
/**
|
||||
* @author Mohsin Husen
|
||||
@@ -26,7 +26,7 @@ public class AliasBuilder {
|
||||
|
||||
private String indexName;
|
||||
private String aliasName;
|
||||
private FilterBuilder filterBuilder;
|
||||
private QueryBuilder filterBuilder;
|
||||
private Map<String, Object> filter;
|
||||
private String searchRouting;
|
||||
private String indexRouting;
|
||||
@@ -42,7 +42,7 @@ public class AliasBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public AliasBuilder withFilterBuilder(FilterBuilder filterBuilder) {
|
||||
public AliasBuilder withFilterBuilder(QueryBuilder filterBuilder) {
|
||||
this.filterBuilder = filterBuilder;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ package org.springframework.data.elasticsearch.core.query;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.elasticsearch.index.query.FilterBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
|
||||
/**
|
||||
* AliasQuery is useful for creating new alias or deleting existing ones
|
||||
@@ -28,7 +28,7 @@ public class AliasQuery {
|
||||
|
||||
private String indexName;
|
||||
private String aliasName;
|
||||
private FilterBuilder filterBuilder;
|
||||
private QueryBuilder filterBuilder;
|
||||
private Map<String, Object> filter;
|
||||
private String searchRouting;
|
||||
private String indexRouting;
|
||||
@@ -50,11 +50,11 @@ public class AliasQuery {
|
||||
this.aliasName = aliasName;
|
||||
}
|
||||
|
||||
public FilterBuilder getFilterBuilder() {
|
||||
public QueryBuilder getFilterBuilder() {
|
||||
return filterBuilder;
|
||||
}
|
||||
|
||||
public void setFilterBuilder(FilterBuilder filterBuilder) {
|
||||
public void setFilterBuilder(QueryBuilder filterBuilder) {
|
||||
this.filterBuilder = filterBuilder;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.elasticsearch.core.geo.GeoBox;
|
||||
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
||||
import org.springframework.data.geo.Box;
|
||||
import org.springframework.data.geo.Distance;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -35,6 +36,17 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class Criteria {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Criteria{" +
|
||||
"field=" + field.getName() +
|
||||
", boost=" + boost +
|
||||
", negating=" + negating +
|
||||
", queryCriteria=" + StringUtils.join(queryCriteria, '|') +
|
||||
", filterCriteria=" + StringUtils.join(filterCriteria, '|') +
|
||||
'}';
|
||||
}
|
||||
|
||||
public static final String WILDCARD = "*";
|
||||
public static final String CRITERIA_VALUE_SEPERATOR = " ";
|
||||
|
||||
@@ -71,7 +83,6 @@ public class Criteria {
|
||||
public Criteria(Field field) {
|
||||
Assert.notNull(field, "Field for criteria must not be null");
|
||||
Assert.hasText(field.getName(), "Field.name for criteria must not be null/empty");
|
||||
|
||||
this.criteriaChain.add(this);
|
||||
this.field = field;
|
||||
}
|
||||
@@ -304,7 +315,18 @@ public class Criteria {
|
||||
* @return
|
||||
*/
|
||||
public Criteria lessThanEqual(Object upperBound) {
|
||||
between(null, upperBound);
|
||||
if (upperBound == null) {
|
||||
throw new InvalidDataAccessApiUsageException("UpperBound can't be null");
|
||||
}
|
||||
queryCriteria.add(new CriteriaEntry(OperationKey.LESS_EQUAL, upperBound));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Criteria lessThan(Object upperBound) {
|
||||
if (upperBound == null) {
|
||||
throw new InvalidDataAccessApiUsageException("UpperBound can't be null");
|
||||
}
|
||||
queryCriteria.add(new CriteriaEntry(OperationKey.LESS, upperBound));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -315,7 +337,18 @@ public class Criteria {
|
||||
* @return
|
||||
*/
|
||||
public Criteria greaterThanEqual(Object lowerBound) {
|
||||
between(lowerBound, null);
|
||||
if (lowerBound == null) {
|
||||
throw new InvalidDataAccessApiUsageException("LowerBound can't be null");
|
||||
}
|
||||
queryCriteria.add(new CriteriaEntry(OperationKey.GREATER_EQUAL, lowerBound));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Criteria greaterThan(Object lowerBound) {
|
||||
if (lowerBound == null) {
|
||||
throw new InvalidDataAccessApiUsageException("LowerBound can't be null");
|
||||
}
|
||||
queryCriteria.add(new CriteriaEntry(OperationKey.GREATER, lowerBound));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -326,12 +359,7 @@ public class Criteria {
|
||||
* @return
|
||||
*/
|
||||
public Criteria in(Object... values) {
|
||||
if (values.length == 0 || (values.length > 1 && values[1] instanceof Collection)) {
|
||||
throw new InvalidDataAccessApiUsageException("At least one element "
|
||||
+ (values.length > 0 ? ("of argument of type " + values[1].getClass().getName()) : "")
|
||||
+ " has to be present.");
|
||||
}
|
||||
return in(Arrays.asList(values));
|
||||
return in(toCollection(values));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -346,6 +374,25 @@ public class Criteria {
|
||||
return this;
|
||||
}
|
||||
|
||||
private List<Object> toCollection(Object... values) {
|
||||
if (values.length == 0 || (values.length > 1 && values[1] instanceof Collection)) {
|
||||
throw new InvalidDataAccessApiUsageException("At least one element "
|
||||
+ (values.length > 0 ? ("of argument of type " + values[1].getClass().getName()) : "")
|
||||
+ " has to be present.");
|
||||
}
|
||||
return Arrays.asList(values);
|
||||
}
|
||||
|
||||
public Criteria notIn(Object... values) {
|
||||
return notIn(toCollection(values));
|
||||
}
|
||||
|
||||
public Criteria notIn(Iterable<?> values) {
|
||||
Assert.notNull(values, "Collection of 'NotIn' values must not be null");
|
||||
queryCriteria.add(new CriteriaEntry(OperationKey.NOT_IN, values));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new CriteriaEntry for {@code location WITHIN distance}
|
||||
*
|
||||
@@ -407,6 +454,17 @@ public class Criteria {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new CriteriaEntry for {@code location Box bounding box}
|
||||
*
|
||||
* @param boundingBox {@link org.springframework.data.elasticsearch.core.geo.GeoBox} bounding box(left top corner + right bottom corner)
|
||||
* @return Criteria the chaind criteria with the new 'boundingBox' criteria included.
|
||||
*/
|
||||
public Criteria boundedBy(Box boundingBox) {
|
||||
Assert.notNull(boundingBox, "boundingBox value for boundedBy criteria must not be null");
|
||||
filterCriteria.add(new CriteriaEntry(OperationKey.BBOX, new Object[]{boundingBox.getFirst(), boundingBox.getSecond()}));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new CriteriaEntry for bounding box created from points
|
||||
@@ -436,10 +494,17 @@ public class Criteria {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Criteria boundedBy(Point topLeftPoint, Point bottomRightPoint) {
|
||||
Assert.notNull(topLeftPoint, "topLeftPoint must not be null");
|
||||
Assert.notNull(bottomRightPoint, "bottomRightPoint must not be null");
|
||||
filterCriteria.add(new CriteriaEntry(OperationKey.BBOX, new Object[]{GeoPoint.fromPoint(topLeftPoint), GeoPoint.fromPoint(bottomRightPoint)}));
|
||||
return this;
|
||||
}
|
||||
|
||||
private void assertNoBlankInWildcardedQuery(String searchString, boolean leadingWildcard, boolean trailingWildcard) {
|
||||
if (StringUtils.contains(searchString, CRITERIA_VALUE_SEPERATOR)) {
|
||||
throw new InvalidDataAccessApiUsageException("Cannot constructQuery '" + (leadingWildcard ? "*" : "") + "\""
|
||||
+ searchString + "\"" + (trailingWildcard ? "*" : "") + "'. Use epxression or mulitple clauses instead.");
|
||||
+ searchString + "\"" + (trailingWildcard ? "*" : "") + "'. Use expression or multiple clauses instead.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -522,7 +587,7 @@ public class Criteria {
|
||||
}
|
||||
|
||||
public enum OperationKey {
|
||||
EQUALS, CONTAINS, STARTS_WITH, ENDS_WITH, EXPRESSION, BETWEEN, FUZZY, IN, WITHIN, BBOX, NEAR;
|
||||
EQUALS, CONTAINS, STARTS_WITH, ENDS_WITH, EXPRESSION, BETWEEN, FUZZY, IN, NOT_IN, WITHIN, BBOX, NEAR, LESS, LESS_EQUAL, GREATER, GREATER_EQUAL;
|
||||
}
|
||||
|
||||
public static class CriteriaEntry {
|
||||
@@ -542,5 +607,13 @@ public class Criteria {
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CriteriaEntry{" +
|
||||
"key=" + key +
|
||||
", value=" + value +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,6 +28,8 @@ public class DeleteQuery {
|
||||
private QueryBuilder query;
|
||||
private String index;
|
||||
private String type;
|
||||
private Integer pageSize;
|
||||
private Long scrollTimeInMillis;
|
||||
|
||||
public QueryBuilder getQuery() {
|
||||
return query;
|
||||
@@ -52,4 +54,20 @@ public class DeleteQuery {
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Integer getPageSize() {
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
public void setPageSize(Integer pageSize) {
|
||||
this.pageSize = pageSize;
|
||||
}
|
||||
|
||||
public Long getScrollTimeInMillis() {
|
||||
return scrollTimeInMillis;
|
||||
}
|
||||
|
||||
public void setScrollTimeInMillis(Long scrollTimeInMillis) {
|
||||
this.scrollTimeInMillis = scrollTimeInMillis;
|
||||
}
|
||||
}
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core.query;
|
||||
|
||||
/**
|
||||
* SourceFilter implementation for providing includes and excludes.
|
||||
*
|
||||
* @Author Jon Tsiros
|
||||
*/
|
||||
public class FetchSourceFilter implements SourceFilter {
|
||||
|
||||
private final String[] includes;
|
||||
private final String[] excludes;
|
||||
|
||||
public FetchSourceFilter(final String[] includes, final String[] excludes) {
|
||||
this.includes = includes;
|
||||
this.excludes = excludes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getIncludes() {
|
||||
return includes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getExcludes() {
|
||||
return excludes;
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core.query;
|
||||
|
||||
/**
|
||||
* SourceFilter builder for providing includes and excludes.
|
||||
*
|
||||
* @Author Jon Tsiros
|
||||
*/
|
||||
public class FetchSourceFilterBuilder {
|
||||
|
||||
private String[] includes;
|
||||
private String[] excludes;
|
||||
|
||||
public FetchSourceFilterBuilder withIncludes(String... includes) {
|
||||
this.includes = includes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FetchSourceFilterBuilder withExcludes(String... excludes) {
|
||||
this.excludes = excludes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SourceFilter build() {
|
||||
if (includes == null) includes = new String[0];
|
||||
if (excludes == null) excludes = new String[0];
|
||||
|
||||
SourceFilter sourceFilter = new FetchSourceFilter(includes, excludes);
|
||||
return sourceFilter;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.elasticsearch.core.query;
|
||||
|
||||
/**
|
||||
* Defines a IndexBoost to be applied on the "indices_boost" query clause
|
||||
*
|
||||
* @author Thiago Locatelli
|
||||
*/
|
||||
public class IndexBoost {
|
||||
|
||||
private String indexName;
|
||||
private float boost;
|
||||
|
||||
public IndexBoost(String indexName, float boost) {
|
||||
this.indexName = indexName;
|
||||
this.boost = boost;
|
||||
}
|
||||
|
||||
public String getIndexName() {
|
||||
return indexName;
|
||||
}
|
||||
|
||||
public float getBoost() {
|
||||
return boost;
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core.query;
|
||||
|
||||
import static org.apache.commons.collections.CollectionUtils.*;
|
||||
import static java.util.Collections.addAll;
|
||||
import static org.springframework.data.elasticsearch.core.query.AbstractQuery.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
+33
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,15 +15,16 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core.query;
|
||||
|
||||
import org.elasticsearch.index.query.FilterBuilder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
||||
import org.elasticsearch.search.highlight.HighlightBuilder;
|
||||
import org.elasticsearch.search.sort.SortBuilder;
|
||||
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* NativeSearchQuery
|
||||
@@ -35,29 +36,31 @@ import java.util.List;
|
||||
public class NativeSearchQuery extends AbstractQuery implements SearchQuery {
|
||||
|
||||
private QueryBuilder query;
|
||||
private FilterBuilder filter;
|
||||
private QueryBuilder filter;
|
||||
private List<SortBuilder> sorts;
|
||||
private final List<ScriptField> scriptFields = new ArrayList<ScriptField>();
|
||||
private List<FacetRequest> facets;
|
||||
private List<AbstractAggregationBuilder> aggregations;
|
||||
private HighlightBuilder.Field[] highlightFields;
|
||||
private List<IndexBoost> indicesBoost;
|
||||
|
||||
|
||||
public NativeSearchQuery(QueryBuilder query) {
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
public NativeSearchQuery(QueryBuilder query, FilterBuilder filter) {
|
||||
public NativeSearchQuery(QueryBuilder query, QueryBuilder filter) {
|
||||
this.query = query;
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
public NativeSearchQuery(QueryBuilder query, FilterBuilder filter, List<SortBuilder> sorts) {
|
||||
public NativeSearchQuery(QueryBuilder query, QueryBuilder filter, List<SortBuilder> sorts) {
|
||||
this.query = query;
|
||||
this.filter = filter;
|
||||
this.sorts = sorts;
|
||||
}
|
||||
|
||||
public NativeSearchQuery(QueryBuilder query, FilterBuilder filter, List<SortBuilder> sorts, HighlightBuilder.Field[] highlightFields) {
|
||||
public NativeSearchQuery(QueryBuilder query, QueryBuilder filter, List<SortBuilder> sorts, HighlightBuilder.Field[] highlightFields) {
|
||||
this.query = query;
|
||||
this.filter = filter;
|
||||
this.sorts = sorts;
|
||||
@@ -68,7 +71,7 @@ public class NativeSearchQuery extends AbstractQuery implements SearchQuery {
|
||||
return query;
|
||||
}
|
||||
|
||||
public FilterBuilder getFilter() {
|
||||
public QueryBuilder getFilter() {
|
||||
return filter;
|
||||
}
|
||||
|
||||
@@ -81,6 +84,17 @@ public class NativeSearchQuery extends AbstractQuery implements SearchQuery {
|
||||
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>();
|
||||
@@ -113,4 +127,14 @@ public class NativeSearchQuery extends AbstractQuery implements SearchQuery {
|
||||
public void setAggregations(List<AbstractAggregationBuilder> aggregations) {
|
||||
this.aggregations = aggregations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IndexBoost> getIndicesBoost() {
|
||||
return indicesBoost;
|
||||
}
|
||||
|
||||
public void setIndicesBoost(List<IndexBoost> indicesBoost) {
|
||||
this.indicesBoost = indicesBoost;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+36
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,13 +15,11 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core.query;
|
||||
|
||||
import static org.springframework.util.CollectionUtils.isEmpty;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.elasticsearch.action.search.SearchType;
|
||||
import org.elasticsearch.index.query.FilterBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
||||
import org.elasticsearch.search.highlight.HighlightBuilder;
|
||||
@@ -40,7 +38,8 @@ import org.springframework.data.elasticsearch.core.facet.FacetRequest;
|
||||
public class NativeSearchQueryBuilder {
|
||||
|
||||
private QueryBuilder queryBuilder;
|
||||
private FilterBuilder filterBuilder;
|
||||
private QueryBuilder filterBuilder;
|
||||
private List<ScriptField> scriptFields = new ArrayList<ScriptField>();
|
||||
private List<SortBuilder> sortBuilders = new ArrayList<SortBuilder>();
|
||||
private List<FacetRequest> facetRequests = new ArrayList<FacetRequest>();
|
||||
private List<AbstractAggregationBuilder> aggregationBuilders = new ArrayList<AbstractAggregationBuilder>();
|
||||
@@ -49,6 +48,8 @@ public class NativeSearchQueryBuilder {
|
||||
private String[] indices;
|
||||
private String[] types;
|
||||
private String[] fields;
|
||||
private SourceFilter sourceFilter;
|
||||
private List<IndexBoost> indicesBoost;
|
||||
private float minScore;
|
||||
private Collection<String> ids;
|
||||
private String route;
|
||||
@@ -59,7 +60,7 @@ public class NativeSearchQueryBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public NativeSearchQueryBuilder withFilter(FilterBuilder filterBuilder) {
|
||||
public NativeSearchQueryBuilder withFilter(QueryBuilder filterBuilder) {
|
||||
this.filterBuilder = filterBuilder;
|
||||
return this;
|
||||
}
|
||||
@@ -69,6 +70,11 @@ public class NativeSearchQueryBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public NativeSearchQueryBuilder withScriptField(ScriptField scriptField) {
|
||||
this.scriptFields.add(scriptField);
|
||||
return this;
|
||||
}
|
||||
|
||||
public NativeSearchQueryBuilder addAggregation(AbstractAggregationBuilder aggregationBuilder) {
|
||||
this.aggregationBuilders.add(aggregationBuilder);
|
||||
return this;
|
||||
@@ -84,6 +90,11 @@ public class NativeSearchQueryBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public NativeSearchQueryBuilder withIndicesBoost(List<IndexBoost> indicesBoost) {
|
||||
this.indicesBoost = indicesBoost;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NativeSearchQueryBuilder withPageable(Pageable pageable) {
|
||||
this.pageable = pageable;
|
||||
return this;
|
||||
@@ -104,6 +115,11 @@ public class NativeSearchQueryBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public NativeSearchQueryBuilder withSourceFilter(SourceFilter sourceFilter) {
|
||||
this.sourceFilter = sourceFilter;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NativeSearchQueryBuilder withMinScore(float minScore) {
|
||||
this.minScore = minScore;
|
||||
return this;
|
||||
@@ -142,11 +158,23 @@ public class NativeSearchQueryBuilder {
|
||||
nativeSearchQuery.addFields(fields);
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(facetRequests)) {
|
||||
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 (CollectionUtils.isNotEmpty(aggregationBuilders)) {
|
||||
if (!isEmpty(aggregationBuilders)) {
|
||||
nativeSearchQuery.setAggregations(aggregationBuilders);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -111,6 +111,21 @@ public interface Query {
|
||||
*/
|
||||
List<String> getFields();
|
||||
|
||||
/**
|
||||
* Add source filter to be added as part of search request
|
||||
*
|
||||
* @param sourceFilter
|
||||
*/
|
||||
void addSourceFilter(SourceFilter sourceFilter);
|
||||
|
||||
/**
|
||||
* Get SourceFilter to be returned to get include and exclude source
|
||||
* fields as part of search request.
|
||||
*
|
||||
* @return SourceFilter
|
||||
*/
|
||||
SourceFilter getSourceFilter();
|
||||
|
||||
/**
|
||||
* Get minimum score
|
||||
*
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.springframework.data.elasticsearch.core.query;
|
||||
|
||||
import org.elasticsearch.script.Script;
|
||||
|
||||
/**
|
||||
* @author Ryan Murfitt
|
||||
* @author Artur Konczak
|
||||
*/
|
||||
public class ScriptField {
|
||||
|
||||
private final String fieldName;
|
||||
private final Script script;
|
||||
|
||||
public ScriptField(String fieldName, Script script) {
|
||||
this.fieldName = fieldName;
|
||||
this.script = script;
|
||||
}
|
||||
|
||||
public String fieldName() {
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
public Script script() {
|
||||
return script;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,7 +17,6 @@ package org.springframework.data.elasticsearch.core.query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.elasticsearch.index.query.FilterBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
||||
import org.elasticsearch.search.highlight.HighlightBuilder;
|
||||
@@ -35,13 +34,19 @@ public interface SearchQuery extends Query {
|
||||
|
||||
QueryBuilder getQuery();
|
||||
|
||||
FilterBuilder getFilter();
|
||||
QueryBuilder getFilter();
|
||||
|
||||
List<SortBuilder> getElasticsearchSorts();
|
||||
|
||||
@Deprecated
|
||||
List<FacetRequest> getFacets();
|
||||
|
||||
List<AbstractAggregationBuilder> getAggregations();
|
||||
|
||||
HighlightBuilder.Field[] getHighlightFields();
|
||||
|
||||
List<IndexBoost> getIndicesBoost();
|
||||
|
||||
List<ScriptField> getScriptFields();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core.query;
|
||||
|
||||
/**
|
||||
* SourceFilter for providing includes and excludes.
|
||||
*
|
||||
* @Author Jon Tsiros
|
||||
*/
|
||||
public interface SourceFilter {
|
||||
|
||||
String[] getIncludes();
|
||||
|
||||
String[] getExcludes();
|
||||
}
|
||||
+7
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,7 +20,6 @@ import java.io.Serializable;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.elasticsearch.core.FacetedPage;
|
||||
import org.springframework.data.elasticsearch.core.query.SearchQuery;
|
||||
import org.springframework.data.repository.NoRepositoryBean;
|
||||
|
||||
@@ -37,9 +36,13 @@ public interface ElasticsearchRepository<T, ID extends Serializable> extends Ela
|
||||
|
||||
Iterable<T> search(QueryBuilder query);
|
||||
|
||||
FacetedPage<T> search(QueryBuilder query, Pageable pageable);
|
||||
Page<T> search(QueryBuilder query, Pageable pageable);
|
||||
|
||||
FacetedPage<T> search(SearchQuery searchQuery);
|
||||
Page<T> search(SearchQuery searchQuery);
|
||||
|
||||
Page<T> searchSimilar(T entity, String[] fields, Pageable pageable);
|
||||
|
||||
void refresh();
|
||||
|
||||
Class<T> getEntityClass();
|
||||
}
|
||||
|
||||
+5
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -33,7 +33,7 @@ import org.springframework.data.repository.cdi.CdiRepositoryBean;
|
||||
import org.springframework.data.repository.cdi.CdiRepositoryExtensionSupport;
|
||||
|
||||
/**
|
||||
* ElasticsearchRepositoryExtension
|
||||
* CDI extension to export Elasticsearch repositories.
|
||||
*
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
@@ -42,14 +42,14 @@ import org.springframework.data.repository.cdi.CdiRepositoryExtensionSupport;
|
||||
*/
|
||||
public class ElasticsearchRepositoryExtension extends CdiRepositoryExtensionSupport {
|
||||
|
||||
private final Map<String, Bean<ElasticsearchOperations>> elasticsearchOperationsMap = new HashMap<String, Bean<ElasticsearchOperations>>();
|
||||
private final Map<Set<Annotation>, Bean<ElasticsearchOperations>> elasticsearchOperationsMap = new HashMap<Set<Annotation>, Bean<ElasticsearchOperations>>();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
<T> void processBean(@Observes ProcessBean<T> processBean) {
|
||||
Bean<T> bean = processBean.getBean();
|
||||
for (Type type : bean.getTypes()) {
|
||||
if (type instanceof Class<?> && ElasticsearchOperations.class.isAssignableFrom((Class<?>) type)) {
|
||||
elasticsearchOperationsMap.put(bean.getQualifiers().toString(), ((Bean<ElasticsearchOperations>) bean));
|
||||
elasticsearchOperationsMap.put(bean.getQualifiers(), ((Bean<ElasticsearchOperations>) bean));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,8 +69,7 @@ public class ElasticsearchRepositoryExtension extends CdiRepositoryExtensionSupp
|
||||
private <T> CdiRepositoryBean<T> createRepositoryBean(Class<T> repositoryType, Set<Annotation> qualifiers,
|
||||
BeanManager beanManager) {
|
||||
|
||||
Bean<ElasticsearchOperations> elasticsearchOperationsBean = this.elasticsearchOperationsMap.get(qualifiers
|
||||
.toString());
|
||||
Bean<ElasticsearchOperations> elasticsearchOperationsBean = this.elasticsearchOperationsMap.get(qualifiers);
|
||||
|
||||
if (elasticsearchOperationsBean == null) {
|
||||
throw new UnsatisfiedResolutionException(String.format("Unable to resolve a bean for '%s' with qualifiers %s.",
|
||||
|
||||
+8
@@ -21,6 +21,7 @@ import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
|
||||
import org.springframework.data.elasticsearch.repository.support.ElasticsearchRepositoryFactoryBean;
|
||||
import org.springframework.data.repository.config.DefaultRepositoryBaseClass;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
|
||||
|
||||
/**
|
||||
@@ -103,6 +104,13 @@ public @interface EnableElasticsearchRepositories {
|
||||
*/
|
||||
Class<?> repositoryFactoryBeanClass() default ElasticsearchRepositoryFactoryBean.class;
|
||||
|
||||
/**
|
||||
* Configure the repository base class to be used to create repository proxies for this particular configuration.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Class<?> repositoryBaseClass() default DefaultRepositoryBaseClass.class;
|
||||
|
||||
// Elasticsearch specific configuration
|
||||
|
||||
/**
|
||||
|
||||
+36
-1
@@ -23,6 +23,9 @@ import org.springframework.data.elasticsearch.repository.query.parser.Elasticsea
|
||||
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
|
||||
@@ -46,9 +49,21 @@ public class ElasticsearchPartQuery extends AbstractElasticsearchRepositoryQuery
|
||||
public Object execute(Object[] parameters) {
|
||||
ParametersParameterAccessor accessor = new ParametersParameterAccessor(queryMethod.getParameters(), parameters);
|
||||
CriteriaQuery query = createQuery(accessor);
|
||||
if (queryMethod.isPageQuery()) {
|
||||
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());
|
||||
@@ -63,6 +78,26 @@ public class ElasticsearchPartQuery extends AbstractElasticsearchRepositoryQuery
|
||||
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();
|
||||
}
|
||||
|
||||
+9
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.data.elasticsearch.annotations.Query;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -28,26 +29,23 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class ElasticsearchQueryMethod extends QueryMethod {
|
||||
|
||||
private Method method;
|
||||
private final Query queryAnnotation;
|
||||
|
||||
public ElasticsearchQueryMethod(Method method, RepositoryMetadata metadata) {
|
||||
super(method, metadata);
|
||||
this.method = method;
|
||||
public ElasticsearchQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory) {
|
||||
super(method, metadata, factory);
|
||||
this.queryAnnotation = method.getAnnotation(Query.class);
|
||||
}
|
||||
|
||||
public boolean hasAnnotatedQuery() {
|
||||
return getQueryAnnotation() != null;
|
||||
return this.queryAnnotation != null;
|
||||
}
|
||||
|
||||
public String getAnnotatedQuery() {
|
||||
String query = (String) AnnotationUtils.getValue(getQueryAnnotation(), "value");
|
||||
String query = (String) AnnotationUtils.getValue(queryAnnotation, "value");
|
||||
return StringUtils.hasText(query) ? query : null;
|
||||
}
|
||||
|
||||
private Query getQueryAnnotation() {
|
||||
return this.method.getAnnotation(Query.class);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-3
@@ -41,6 +41,7 @@ import org.springframework.data.repository.query.parser.PartTree;
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Franck Marchand
|
||||
* @author Artur Konczak
|
||||
*/
|
||||
public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuery, CriteriaQuery> {
|
||||
|
||||
@@ -112,12 +113,14 @@ public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuer
|
||||
return criteria.endsWith(parameters.next().toString());
|
||||
case CONTAINING:
|
||||
return criteria.contains(parameters.next().toString());
|
||||
case AFTER:
|
||||
case GREATER_THAN:
|
||||
return criteria.greaterThan(parameters.next());
|
||||
case AFTER:
|
||||
case GREATER_THAN_EQUAL:
|
||||
return criteria.greaterThanEqual(parameters.next());
|
||||
case BEFORE:
|
||||
case LESS_THAN:
|
||||
return criteria.lessThan(parameters.next());
|
||||
case BEFORE:
|
||||
case LESS_THAN_EQUAL:
|
||||
return criteria.lessThanEqual(parameters.next());
|
||||
case BETWEEN:
|
||||
@@ -125,7 +128,7 @@ public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuer
|
||||
case IN:
|
||||
return criteria.in(asArray(parameters.next()));
|
||||
case NOT_IN:
|
||||
return criteria.in(asArray(parameters.next())).not();
|
||||
return criteria.notIn(asArray(parameters.next()));
|
||||
case SIMPLE_PROPERTY:
|
||||
case WITHIN: {
|
||||
Object firstParameter = parameters.next();
|
||||
|
||||
+41
-38
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2014 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,13 +15,12 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.repository.support;
|
||||
|
||||
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -30,19 +29,9 @@ import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.*;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.FacetedPage;
|
||||
import org.springframework.data.elasticsearch.core.query.DeleteQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.GetQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.IndexQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.MoreLikeThisQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
|
||||
import org.springframework.data.elasticsearch.core.query.SearchQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.*;
|
||||
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -54,6 +43,7 @@ import org.springframework.util.Assert;
|
||||
* @author Mohsin Husen
|
||||
* @author Ryan Henszey
|
||||
* @author Kevin Leturc
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public abstract class AbstractElasticsearchRepository<T, ID extends Serializable> implements
|
||||
ElasticsearchRepository<T, ID> {
|
||||
@@ -67,19 +57,25 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
|
||||
}
|
||||
|
||||
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) {
|
||||
this(elasticsearchOperations);
|
||||
Assert.notNull(metadata);
|
||||
|
||||
Assert.notNull(metadata, "ElasticsearchEntityInformation must not be null!");
|
||||
|
||||
this.entityInformation = metadata;
|
||||
setEntityClass(this.entityInformation.getJavaType());
|
||||
try {
|
||||
createIndex();
|
||||
putMapping();
|
||||
if (createIndexAndMapping()) {
|
||||
createIndex();
|
||||
putMapping();
|
||||
}
|
||||
} catch (ElasticsearchException exception) {
|
||||
LOGGER.error("failed to load elasticsearch nodes : " + exception.getDetailedMessage());
|
||||
}
|
||||
@@ -93,6 +89,10 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
|
||||
elasticsearchOperations.putMapping(getEntityClass());
|
||||
}
|
||||
|
||||
private boolean createIndexAndMapping() {
|
||||
return elasticsearchOperations.getPersistentEntityFor(getEntityClass()).isCreateIndexAndMapping();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T findOne(ID id) {
|
||||
GetQuery query = new GetQuery();
|
||||
@@ -145,7 +145,7 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
|
||||
public <S extends T> S save(S entity) {
|
||||
Assert.notNull(entity, "Cannot save 'null' entity.");
|
||||
elasticsearchOperations.index(createIndexQuery(entity));
|
||||
elasticsearchOperations.refresh(entityInformation.getIndexName(), true);
|
||||
elasticsearchOperations.refresh(entityInformation.getIndexName());
|
||||
return entity;
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
|
||||
queries.add(createIndexQuery(s));
|
||||
}
|
||||
elasticsearchOperations.bulkIndex(queries);
|
||||
elasticsearchOperations.refresh(entityInformation.getIndexName(), true);
|
||||
elasticsearchOperations.refresh(entityInformation.getIndexName());
|
||||
return entities;
|
||||
}
|
||||
|
||||
@@ -169,15 +169,12 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
|
||||
@Override
|
||||
public <S extends T> Iterable<S> save(Iterable<S> entities) {
|
||||
Assert.notNull(entities, "Cannot insert 'null' as a List.");
|
||||
if (!(entities instanceof Collection<?>)) {
|
||||
throw new InvalidDataAccessApiUsageException("Entities have to be inside a collection");
|
||||
}
|
||||
List<IndexQuery> queries = new ArrayList<IndexQuery>();
|
||||
for (S s : entities) {
|
||||
queries.add(createIndexQuery(s));
|
||||
}
|
||||
elasticsearchOperations.bulkIndex(queries);
|
||||
elasticsearchOperations.refresh(entityInformation.getIndexName(), true);
|
||||
elasticsearchOperations.refresh(entityInformation.getIndexName());
|
||||
return entities;
|
||||
}
|
||||
|
||||
@@ -198,13 +195,13 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
|
||||
}
|
||||
|
||||
@Override
|
||||
public FacetedPage<T> search(QueryBuilder query, Pageable pageable) {
|
||||
public Page<T> search(QueryBuilder query, Pageable pageable) {
|
||||
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(query).withPageable(pageable).build();
|
||||
return elasticsearchOperations.queryForPage(searchQuery, getEntityClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FacetedPage<T> search(SearchQuery query) {
|
||||
public Page<T> search(SearchQuery query) {
|
||||
return elasticsearchOperations.queryForPage(query, getEntityClass());
|
||||
}
|
||||
|
||||
@@ -226,14 +223,14 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
|
||||
Assert.notNull(id, "Cannot delete entity with id 'null'.");
|
||||
elasticsearchOperations.delete(entityInformation.getIndexName(), entityInformation.getType(),
|
||||
stringIdRepresentation(id));
|
||||
elasticsearchOperations.refresh(entityInformation.getIndexName(), true);
|
||||
elasticsearchOperations.refresh(entityInformation.getIndexName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(T entity) {
|
||||
Assert.notNull(entity, "Cannot delete 'null' entity.");
|
||||
delete(extractIdFromBean(entity));
|
||||
elasticsearchOperations.refresh(entityInformation.getIndexName(), true);
|
||||
elasticsearchOperations.refresh(entityInformation.getIndexName());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -249,7 +246,12 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
|
||||
DeleteQuery deleteQuery = new DeleteQuery();
|
||||
deleteQuery.setQuery(matchAllQuery());
|
||||
elasticsearchOperations.delete(deleteQuery, getEntityClass());
|
||||
elasticsearchOperations.refresh(entityInformation.getIndexName(), true);
|
||||
elasticsearchOperations.refresh(entityInformation.getIndexName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
elasticsearchOperations.refresh(getEntityClass());
|
||||
}
|
||||
|
||||
private IndexQuery createIndexQuery(T entity) {
|
||||
@@ -279,6 +281,7 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
|
||||
return resolveReturnedClassFromGenericType(clazz.getSuperclass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> getEntityClass() {
|
||||
if (!isEntityClassSet()) {
|
||||
try {
|
||||
@@ -311,14 +314,14 @@ public abstract class AbstractElasticsearchRepository<T, ID extends Serializable
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<String> stringIdsRepresentation(Iterable<ID> ids) {
|
||||
Assert.notNull(ids, "ids can't be null.");
|
||||
List<String> stringIds = new ArrayList<String>();
|
||||
for (ID id : ids) {
|
||||
stringIds.add(stringIdRepresentation(id));
|
||||
}
|
||||
return stringIds;
|
||||
}
|
||||
private List<String> stringIdsRepresentation(Iterable<ID> ids) {
|
||||
Assert.notNull(ids, "ids can't be null.");
|
||||
List<String> stringIds = new ArrayList<String>();
|
||||
for (ID id : ids) {
|
||||
stringIds.add(stringIdRepresentation(id));
|
||||
}
|
||||
return stringIds;
|
||||
}
|
||||
|
||||
protected abstract String stringIdRepresentation(ID id);
|
||||
|
||||
|
||||
+5
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2014 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.
|
||||
@@ -28,6 +28,7 @@ import org.springframework.util.Assert;
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class ElasticsearchEntityInformationCreatorImpl implements ElasticsearchEntityInformationCreator {
|
||||
|
||||
@@ -35,7 +36,9 @@ public class ElasticsearchEntityInformationCreatorImpl implements ElasticsearchE
|
||||
|
||||
public ElasticsearchEntityInformationCreatorImpl(
|
||||
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext) {
|
||||
Assert.notNull(mappingContext);
|
||||
|
||||
Assert.notNull(mappingContext, "MappingContext must not be null!");
|
||||
|
||||
this.mappingContext = mappingContext;
|
||||
}
|
||||
|
||||
|
||||
+122
-120
@@ -1,120 +1,122 @@
|
||||
/*
|
||||
* 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 static org.springframework.data.querydsl.QueryDslUtils.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
|
||||
import org.springframework.data.elasticsearch.repository.query.ElasticsearchPartQuery;
|
||||
import org.springframework.data.elasticsearch.repository.query.ElasticsearchQueryMethod;
|
||||
import org.springframework.data.elasticsearch.repository.query.ElasticsearchStringQuery;
|
||||
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
|
||||
import org.springframework.data.repository.core.NamedQueries;
|
||||
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.RepositoryQuery;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Factory to create {@link ElasticsearchRepository}
|
||||
*
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Ryan Henszey
|
||||
*/
|
||||
public class ElasticsearchRepositoryFactory extends RepositoryFactorySupport {
|
||||
|
||||
private final ElasticsearchOperations elasticsearchOperations;
|
||||
private final ElasticsearchEntityInformationCreator entityInformationCreator;
|
||||
|
||||
public ElasticsearchRepositoryFactory(ElasticsearchOperations elasticsearchOperations) {
|
||||
Assert.notNull(elasticsearchOperations);
|
||||
this.elasticsearchOperations = elasticsearchOperations;
|
||||
this.entityInformationCreator = new ElasticsearchEntityInformationCreatorImpl(elasticsearchOperations
|
||||
.getElasticsearchConverter().getMappingContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, ID extends Serializable> ElasticsearchEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
|
||||
return entityInformationCreator.getEntityInformation(domainClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
protected Object getTargetRepository(RepositoryMetadata metadata) {
|
||||
|
||||
ElasticsearchEntityInformation<?, ?> entityInformation = getEntityInformation(metadata.getDomainType());
|
||||
|
||||
AbstractElasticsearchRepository repository;
|
||||
|
||||
// Probably a better way to store and look these up.
|
||||
if (Integer.class.isAssignableFrom(entityInformation.getIdType())
|
||||
|| Long.class.isAssignableFrom(entityInformation.getIdType())
|
||||
|| Double.class.isAssignableFrom(entityInformation.getIdType())) {
|
||||
// logger.debug("Using NumberKeyedRepository for " + metadata.getRepositoryInterface());
|
||||
repository = new NumberKeyedRepository(getEntityInformation(metadata.getDomainType()), elasticsearchOperations);
|
||||
} else if (entityInformation.getIdType() == String.class) {
|
||||
// logger.debug("Using SimpleElasticsearchRepository for " + metadata.getRepositoryInterface());
|
||||
repository = new SimpleElasticsearchRepository(getEntityInformation(metadata.getDomainType()),
|
||||
elasticsearchOperations);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsuppored ID type " + entityInformation.getIdType());
|
||||
}
|
||||
repository.setEntityClass(metadata.getDomainType());
|
||||
|
||||
return repository;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
|
||||
if (isQueryDslRepository(metadata.getRepositoryInterface())) {
|
||||
throw new IllegalArgumentException("QueryDsl Support has not been implemented yet.");
|
||||
}
|
||||
return SimpleElasticsearchRepository.class;
|
||||
}
|
||||
|
||||
private static boolean isQueryDslRepository(Class<?> repositoryInterface) {
|
||||
return QUERY_DSL_PRESENT && QueryDslPredicateExecutor.class.isAssignableFrom(repositoryInterface);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QueryLookupStrategy getQueryLookupStrategy(QueryLookupStrategy.Key key) {
|
||||
return new ElasticsearchQueryLookupStrategy();
|
||||
}
|
||||
|
||||
private class ElasticsearchQueryLookupStrategy implements QueryLookupStrategy {
|
||||
|
||||
@Override
|
||||
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, NamedQueries namedQueries) {
|
||||
|
||||
ElasticsearchQueryMethod queryMethod = new ElasticsearchQueryMethod(method, metadata);
|
||||
String namedQueryName = queryMethod.getNamedQueryName();
|
||||
|
||||
if (namedQueries.hasQuery(namedQueryName)) {
|
||||
String namedQuery = namedQueries.getQuery(namedQueryName);
|
||||
return new ElasticsearchStringQuery(queryMethod, elasticsearchOperations, namedQuery);
|
||||
} else if (queryMethod.hasAnnotatedQuery()) {
|
||||
return new ElasticsearchStringQuery(queryMethod, elasticsearchOperations, queryMethod.getAnnotatedQuery());
|
||||
}
|
||||
return new ElasticsearchPartQuery(queryMethod, elasticsearchOperations);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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 static org.springframework.data.querydsl.QueryDslUtils.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
|
||||
import org.springframework.data.elasticsearch.repository.query.ElasticsearchPartQuery;
|
||||
import org.springframework.data.elasticsearch.repository.query.ElasticsearchQueryMethod;
|
||||
import org.springframework.data.elasticsearch.repository.query.ElasticsearchStringQuery;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
|
||||
import org.springframework.data.repository.core.NamedQueries;
|
||||
import org.springframework.data.repository.core.RepositoryInformation;
|
||||
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.RepositoryQuery;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Factory to create {@link ElasticsearchRepository}
|
||||
*
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Ryan Henszey
|
||||
* @author Gad Akuka
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class ElasticsearchRepositoryFactory extends RepositoryFactorySupport {
|
||||
|
||||
private final ElasticsearchOperations elasticsearchOperations;
|
||||
private final ElasticsearchEntityInformationCreator entityInformationCreator;
|
||||
|
||||
public ElasticsearchRepositoryFactory(ElasticsearchOperations elasticsearchOperations) {
|
||||
|
||||
Assert.notNull(elasticsearchOperations, "ElasticsearchOperations must not be null!");
|
||||
|
||||
this.elasticsearchOperations = elasticsearchOperations;
|
||||
this.entityInformationCreator = new ElasticsearchEntityInformationCreatorImpl(elasticsearchOperations
|
||||
.getElasticsearchConverter().getMappingContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, ID extends Serializable> ElasticsearchEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
|
||||
return entityInformationCreator.getEntityInformation(domainClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
protected Object getTargetRepository(RepositoryInformation metadata) {
|
||||
return getTargetRepositoryViaReflection(metadata,getEntityInformation(metadata.getDomainType()), elasticsearchOperations);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
|
||||
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())
|
||||
|| Double.class.isAssignableFrom(metadata.getIdType())) {
|
||||
return NumberKeyedRepository.class;
|
||||
} else if (metadata.getIdType() == String.class) {
|
||||
return SimpleElasticsearchRepository.class;
|
||||
} else if (metadata.getIdType() == UUID.class) {
|
||||
return UUIDElasticsearchRepository.class;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported ID type " + metadata.getIdType());
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isQueryDslRepository(Class<?> repositoryInterface) {
|
||||
return QUERY_DSL_PRESENT && QueryDslPredicateExecutor.class.isAssignableFrom(repositoryInterface);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QueryLookupStrategy getQueryLookupStrategy(QueryLookupStrategy.Key key) {
|
||||
return new ElasticsearchQueryLookupStrategy();
|
||||
}
|
||||
|
||||
private class ElasticsearchQueryLookupStrategy implements QueryLookupStrategy {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.QueryLookupStrategy#resolveQuery(java.lang.reflect.Method, org.springframework.data.repository.core.RepositoryMetadata, org.springframework.data.projection.ProjectionFactory, org.springframework.data.repository.core.NamedQueries)
|
||||
*/
|
||||
@Override
|
||||
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory,
|
||||
NamedQueries namedQueries) {
|
||||
|
||||
ElasticsearchQueryMethod queryMethod = new ElasticsearchQueryMethod(method, metadata, factory);
|
||||
String namedQueryName = queryMethod.getNamedQueryName();
|
||||
|
||||
if (namedQueries.hasQuery(namedQueryName)) {
|
||||
String namedQuery = namedQueries.getQuery(namedQueryName);
|
||||
return new ElasticsearchStringQuery(queryMethod, elasticsearchOperations, namedQuery);
|
||||
} else if (queryMethod.hasAnnotatedQuery()) {
|
||||
return new ElasticsearchStringQuery(queryMethod, elasticsearchOperations, queryMethod.getAnnotatedQuery());
|
||||
}
|
||||
return new ElasticsearchPartQuery(queryMethod, elasticsearchOperations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-2
@@ -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,32 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
+7
-25
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,8 +21,7 @@ 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.mapping.model.BeanWrapper;
|
||||
import org.springframework.data.repository.core.support.AbstractEntityInformation;
|
||||
import org.springframework.data.repository.core.support.PersistentEntityInformation;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -34,44 +33,27 @@ import org.springframework.util.Assert;
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Ryan Henszey
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MappingElasticsearchEntityInformation<T, ID extends Serializable> extends AbstractEntityInformation<T, ID>
|
||||
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;
|
||||
private Class<?> idClass;
|
||||
|
||||
public MappingElasticsearchEntityInformation(ElasticsearchPersistentEntity<T> entity) {
|
||||
this(entity, null, null);
|
||||
}
|
||||
|
||||
public MappingElasticsearchEntityInformation(ElasticsearchPersistentEntity<T> entity, String indexName, String type) {
|
||||
super(entity.getType());
|
||||
super(entity);
|
||||
this.entityMetadata = entity;
|
||||
this.indexName = indexName;
|
||||
this.type = type;
|
||||
this.idClass = entity.getIdProperty().getType();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public ID getId(T entity) {
|
||||
ElasticsearchPersistentProperty id = entityMetadata.getIdProperty();
|
||||
try {
|
||||
return (ID) BeanWrapper.create(entity, null).getProperty(id);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("ID could not be resolved", e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Class<ID> getIdType() {
|
||||
return (Class<ID>) idClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdAttribute() {
|
||||
@@ -96,7 +78,7 @@ public class MappingElasticsearchEntityInformation<T, ID extends Serializable> e
|
||||
ElasticsearchPersistentProperty versionProperty = entityMetadata.getVersionProperty();
|
||||
try {
|
||||
if (versionProperty != null) {
|
||||
return (Long) BeanWrapper.create(entity, null).getProperty(versionProperty);
|
||||
return (Long) entityMetadata.getPropertyAccessor(entity).getProperty(versionProperty);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("failed to load version field", e);
|
||||
@@ -109,7 +91,7 @@ public class MappingElasticsearchEntityInformation<T, ID extends Serializable> e
|
||||
ElasticsearchPersistentProperty parentProperty = entityMetadata.getParentIdProperty();
|
||||
try {
|
||||
if (parentProperty != null) {
|
||||
return (String) BeanWrapper.create(entity, null).getProperty(parentProperty);
|
||||
return (String) entityMetadata.getPropertyAccessor(entity).getProperty(parentProperty);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("failed to load parent ID: " + e, e);
|
||||
|
||||
+47
@@ -0,0 +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 java.util.UUID;
|
||||
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
|
||||
/**
|
||||
* Elasticsearch specific repository implementation. Likely to be used as target within
|
||||
* {@link ElasticsearchRepositoryFactory}
|
||||
*
|
||||
* @author Gad Akuka
|
||||
*/
|
||||
public class UUIDElasticsearchRepository<T> extends AbstractElasticsearchRepository<T, UUID> {
|
||||
|
||||
public UUIDElasticsearchRepository() {
|
||||
super();
|
||||
}
|
||||
|
||||
public UUIDElasticsearchRepository(ElasticsearchEntityInformation<T, UUID> metadata,
|
||||
ElasticsearchOperations elasticsearchOperations) {
|
||||
super(metadata, elasticsearchOperations);
|
||||
}
|
||||
|
||||
public UUIDElasticsearchRepository(ElasticsearchOperations elasticsearchOperations) {
|
||||
super(elasticsearchOperations);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String stringIdRepresentation(UUID id) {
|
||||
return (id != null) ? id.toString() : null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
org.springframework.data.repository.core.support.RepositoryFactorySupport=org.springframework.data.elasticsearch.repository.support.ElasticsearchRepositoryFactory
|
||||
@@ -1,6 +1,180 @@
|
||||
Spring Data Elasticsearch Changelog
|
||||
===================================
|
||||
|
||||
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).
|
||||
|
||||
|
||||
Changes in version 2.0.4.RELEASE (2016-09-29)
|
||||
---------------------------------------------
|
||||
* DATAES-297 - Release 2.0.4 (Hopper SR4).
|
||||
|
||||
|
||||
Changes in version 1.3.6.RELEASE (2016-09-29)
|
||||
---------------------------------------------
|
||||
* DATAES-299 - Release 1.3.6 (Gosling SR6).
|
||||
|
||||
|
||||
Changes in version 1.3.5.RELEASE (2016-09-20)
|
||||
---------------------------------------------
|
||||
* DATAES-296 - Release 1.3.5 (Gosling SR5).
|
||||
|
||||
|
||||
Changes in version 2.0.3.RELEASE (2016-09-20)
|
||||
---------------------------------------------
|
||||
* DATAES-281 - Can't save entity without id setter.
|
||||
* DATAES-268 - Release 2.0.3 (Hopper SR3).
|
||||
|
||||
|
||||
Changes in version 2.1.0.M1 (2016-07-27)
|
||||
----------------------------------------
|
||||
* DATAES-262 - Upgrade Elasticsearch to 2.3.3.
|
||||
* DATAES-250 - Release 2.1 M1 (Ingalls).
|
||||
|
||||
|
||||
Changes in version 2.0.2.RELEASE (2016-06-15)
|
||||
---------------------------------------------
|
||||
* DATAES-251 - Release 2.0.2 (Hopper SR2).
|
||||
|
||||
|
||||
Changes in version 2.0.1.RELEASE (2016-04-06)
|
||||
---------------------------------------------
|
||||
* DATAES-249 - Release 2.0.1 (Hopper SR1).
|
||||
|
||||
|
||||
Changes in version 2.0.0.RELEASE (2016-04-06)
|
||||
---------------------------------------------
|
||||
* DATAES-245 - Release 2.0 GA (Hopper).
|
||||
|
||||
|
||||
Changes in version 2.0.0.RC1 (2016-03-18)
|
||||
-----------------------------------------
|
||||
* DATAES-241 - remove commons-collections dependency and use CollectionUtils from Spring Utils.
|
||||
* DATAES-240 - Release 2.0 RC1 (Hopper).
|
||||
* DATAES-238 - ElasticsearchTemplate.prepareUpdate() does not preserve routing parameter which is required for updating child documents.
|
||||
* DATAES-237 - path-configuration fails to load configs from inside jars.
|
||||
* DATAES-236 - Clear the search contexts associated with specified scroll id.
|
||||
* DATAES-234 - CDI support can fail due to Set.toString() used as Map key.
|
||||
* DATAES-211 - Upgrade to Elasticsearch 2.0.
|
||||
* DATAES-188 - Source filtering feature Implementation.
|
||||
* DATAES-124 - ElasticSearchTemplate should expose client.
|
||||
|
||||
|
||||
Changes in version 1.4.0.M1 (2016-02-12)
|
||||
----------------------------------------
|
||||
* DATAES-232 - Add code of conduct.
|
||||
* DATAES-231 - Release 1.4 M1 (Hopper).
|
||||
* DATAES-230 - Remove unnecessary type check in AbstractElasticsearchRepository.
|
||||
* DATAES-224 - ElasticsearchTemplate discards newlines in mappings and settings files.
|
||||
* DATAES-221 - Adapt to changes in Spring Data Commons.
|
||||
* DATAES-216 - Add support to Indices Boost.
|
||||
* DATAES-210 - Typo in error message.
|
||||
* DATAES-209 - Handle dynamic mapping annotation at field level.
|
||||
* DATAES-194 - Tests should clean up "data" directory.
|
||||
* DATAES-171 - findByIdNotIn not work.
|
||||
* DATAES-94 - Bump to support ES 1.2.0.
|
||||
|
||||
|
||||
Changes in version 1.3.2.RELEASE (2015-12-18)
|
||||
---------------------------------------------
|
||||
* DATAES-223 - Release 1.3.2 (Gosling).
|
||||
|
||||
|
||||
Changes in version 1.3.1.RELEASE (2015-11-15)
|
||||
---------------------------------------------
|
||||
* DATAES-212 - Release 1.3.1 (Gosling).
|
||||
|
||||
|
||||
Changes in version 1.1.4.RELEASE (2015-10-14)
|
||||
---------------------------------------------
|
||||
* DATAES-202 - Release 1.1.4 (Evans).
|
||||
|
||||
|
||||
Changes in version 1.3.0.RELEASE (2015-09-01)
|
||||
---------------------------------------------
|
||||
* DATAES-193 - Release 1.3 GA (Gosling).
|
||||
* DATAES-137 - Should work out of the box with Spring Data REST.
|
||||
|
||||
|
||||
Changes in version 1.3.0.RC1 (2015-08-04)
|
||||
-----------------------------------------
|
||||
* DATAES-186 - Release 1.3 RC1 (Gosling).
|
||||
* DATAES-182 - Switch from BeanWrapper to PersistentPropertyAccessor.
|
||||
|
||||
|
||||
Changes in version 1.2.2.RELEASE (2015-07-28)
|
||||
---------------------------------------------
|
||||
* DATAES-184 - Release 1.2.2 (Fowler).
|
||||
|
||||
|
||||
Changes in version 1.0.6.RELEASE (2015-07-01)
|
||||
---------------------------------------------
|
||||
* DATAES-173 - Release 1.0.6 (Dijkstra).
|
||||
|
||||
|
||||
Changes in version 1.1.3.RELEASE (2015-07-01)
|
||||
---------------------------------------------
|
||||
* DATAES-174 - Release 1.1.3 (Evans).
|
||||
|
||||
|
||||
Changes in version 1.2.1.RELEASE (2015-06-30)
|
||||
---------------------------------------------
|
||||
* DATAES-175 - Release 1.2.1 (Fowler).
|
||||
* DATAES-164 - CriteriaQuery equals method has to use AND operator instead of OR.
|
||||
* DATAES-155 - findAll(Iterable<ID> ids) doesn't set persistent entity id.
|
||||
|
||||
|
||||
Changes in version 1.3.0.M1 (2015-06-02)
|
||||
----------------------------------------
|
||||
* DATAES-168 - Release 1.3 M1 (Gosling).
|
||||
* DATAES-164 - CriteriaQuery equals method has to use AND operator instead of OR.
|
||||
* DATAES-162 - Adapt API changes in Spring Data Commons to simplify custom repository base class registration.
|
||||
* DATAES-159 - Bulk update with ElasticsearchTemplate.
|
||||
* DATAES-158 - UpdateRequest.script not working.
|
||||
* DATAES-157 - support deleteBy operation.
|
||||
* DATAES-155 - findAll(Iterable<ID> ids) doesn't set persistent entity id.
|
||||
|
||||
|
||||
Changes in version 1.2.0.RELEASE (2015-03-23)
|
||||
---------------------------------------------
|
||||
* DATAES-154 - Release 1.2 GA.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Spring Data Elasticsearch 1.2 GA
|
||||
Copyright (c) [2013-2015] Pivotal Software, Inc.
|
||||
Spring Data Elasticsearch 2.1.1
|
||||
Copyright (c) [2013-2016] Pivotal Software, Inc.
|
||||
|
||||
This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
||||
You may not use this product except in compliance with the License.
|
||||
|
||||
+45
-15
@@ -5,7 +5,8 @@
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
xmlns:repository="http://www.springframework.org/schema/data/repository"
|
||||
targetNamespace="http://www.springframework.org/schema/data/elasticsearch"
|
||||
elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
elementFormDefault="qualified"
|
||||
attributeFormDefault="unqualified">
|
||||
|
||||
<xsd:import namespace="http://www.springframework.org/schema/beans"/>
|
||||
<xsd:import namespace="http://www.springframework.org/schema/tool"/>
|
||||
@@ -37,7 +38,7 @@
|
||||
|
||||
<xsd:element name="node-client">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java: org.springframework.data.elasticsearch.client.NodeClientFactoryBean"/>
|
||||
<xsd:documentation/>
|
||||
<xsd:appinfo>
|
||||
<tool:assignable-to type="org.elasticsearch.client.Client"/>
|
||||
</xsd:appinfo>
|
||||
@@ -48,28 +49,52 @@
|
||||
<xsd:attribute name="local" type="xsd:boolean" default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[local here means local on the JVM (well, actually class loader) level, meaning that two local servers started within the same JVM will discover themselves and form a cluster]]></xsd:documentation>
|
||||
<![CDATA[local here means local on the JVM (well, actually class loader) level, meaning that two local servers started within the same JVM will discover themselves and form a cluster]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="cluster-name" type="xsd:string" default="elasticsearch">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[Name of the cluster in which this instance of node client will connect to]]> </xsd:documentation>
|
||||
<![CDATA[Name of the cluster in which this instance of node client will connect to]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="http-enabled" type="xsd:boolean" default="true">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[to enable or desable http port]]> </xsd:documentation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[ to enable or disable http port ]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="path-data" type="xsd:string" default="">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[ path to the data folder for node client ]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="path-home" type="xsd:string" default="">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[ path to the home folder for node client ]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="path-configuration" type="xsd:string" default="">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[ path to configuration file for node client ]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="transport-client">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java: org.springframework.data.elasticsearch.client.TransportClientFactoryBean"/>
|
||||
<xsd:documentation/>
|
||||
<xsd:appinfo>
|
||||
<tool:assignable-to type="org.elasticsearch.client.Client"/>
|
||||
</xsd:appinfo>
|
||||
@@ -80,42 +105,47 @@
|
||||
<xsd:attribute name="cluster-nodes" type="xsd:string" default="127.0.0.1:9300">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[The comma delimited list of host:port entries to use for elasticsearch cluster.]]></xsd:documentation>
|
||||
<![CDATA[The comma delimited list of host:port entries to use for elasticsearch cluster.]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="cluster-name" type="xsd:string" default="elasticsearch">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[Name of the cluster in which this instance of node client will connect to]]> </xsd:documentation>
|
||||
<![CDATA[Name of the cluster in which this instance of node client will connect to]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="client-transport-sniff" type="xsd:boolean" default="true">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[The client allows to sniff the rest of the cluster, and add those into its list of machines to use.]]> </xsd:documentation>
|
||||
<![CDATA[The client allows to sniff the rest of the cluster, and add those into its list of machines to use.]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="client-transport-ignore-cluster-name" type="xsd:boolean" default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[Set to true to ignore cluster name validation of connected nodes. (since 0.19.4)]]> </xsd:documentation>
|
||||
<![CDATA[Set to true to ignore cluster name validation of connected nodes. (since 0.19.4)]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="client-transport-ping-timeout" type="xsd:string" default="5s">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[The time to wait for a ping response from a node. Defaults to 5s.]]> </xsd:documentation>
|
||||
<![CDATA[The time to wait for a ping response from a node. Defaults to 5s.]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="client-transport-nodes-sampler-interval" type="xsd:string" default="5s">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[How often to sample / ping the nodes listed and connected. Defaults to 5s.]]> </xsd:documentation>
|
||||
<![CDATA[How often to sample / ping the nodes listed and connected. Defaults to 5s.]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
</xsd:schema>
|
||||
</xsd:schema>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -50,7 +50,7 @@ public class InnerObjectTests {
|
||||
elasticsearchTemplate.deleteIndex(Book.class);
|
||||
elasticsearchTemplate.createIndex(Book.class);
|
||||
elasticsearchTemplate.putMapping(Book.class);
|
||||
elasticsearchTemplate.refresh(Book.class, true);
|
||||
elasticsearchTemplate.refresh(Book.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -48,6 +48,7 @@ import org.springframework.data.elasticsearch.entities.Car;
|
||||
import org.springframework.data.elasticsearch.entities.GirlFriend;
|
||||
import org.springframework.data.elasticsearch.entities.Person;
|
||||
import org.springframework.data.elasticsearch.entities.PersonMultipleLevelNested;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@@ -69,15 +70,15 @@ public class NestedObjectTests {
|
||||
elasticsearchTemplate.deleteIndex(Book.class);
|
||||
elasticsearchTemplate.createIndex(Book.class);
|
||||
elasticsearchTemplate.putMapping(Book.class);
|
||||
elasticsearchTemplate.refresh(Book.class, true);
|
||||
elasticsearchTemplate.refresh(Book.class);
|
||||
elasticsearchTemplate.deleteIndex(Person.class);
|
||||
elasticsearchTemplate.createIndex(Person.class);
|
||||
elasticsearchTemplate.putMapping(Person.class);
|
||||
elasticsearchTemplate.refresh(Person.class, true);
|
||||
elasticsearchTemplate.refresh(Person.class);
|
||||
elasticsearchTemplate.deleteIndex(PersonMultipleLevelNested.class);
|
||||
elasticsearchTemplate.createIndex(PersonMultipleLevelNested.class);
|
||||
elasticsearchTemplate.putMapping(PersonMultipleLevelNested.class);
|
||||
elasticsearchTemplate.refresh(PersonMultipleLevelNested.class, true);
|
||||
elasticsearchTemplate.refresh(PersonMultipleLevelNested.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -129,7 +130,7 @@ public class NestedObjectTests {
|
||||
|
||||
elasticsearchTemplate.putMapping(Person.class);
|
||||
elasticsearchTemplate.bulkIndex(indexQueries);
|
||||
elasticsearchTemplate.refresh(Person.class, true);
|
||||
elasticsearchTemplate.refresh(Person.class);
|
||||
|
||||
final QueryBuilder builder = nestedQuery("car", boolQuery().must(termQuery("car.name", "saturn")).must(termQuery("car.model", "imprezza")));
|
||||
|
||||
@@ -147,7 +148,7 @@ public class NestedObjectTests {
|
||||
//when
|
||||
elasticsearchTemplate.putMapping(PersonMultipleLevelNested.class);
|
||||
elasticsearchTemplate.bulkIndex(indexQueries);
|
||||
elasticsearchTemplate.refresh(PersonMultipleLevelNested.class, true);
|
||||
elasticsearchTemplate.refresh(PersonMultipleLevelNested.class);
|
||||
|
||||
//then
|
||||
final GetQuery getQuery = new GetQuery();
|
||||
@@ -184,7 +185,7 @@ public class NestedObjectTests {
|
||||
//when
|
||||
elasticsearchTemplate.putMapping(PersonMultipleLevelNested.class);
|
||||
elasticsearchTemplate.bulkIndex(indexQueries);
|
||||
elasticsearchTemplate.refresh(PersonMultipleLevelNested.class, true);
|
||||
elasticsearchTemplate.refresh(PersonMultipleLevelNested.class);
|
||||
|
||||
//then
|
||||
final BoolQueryBuilder builder = boolQuery();
|
||||
@@ -325,7 +326,7 @@ public class NestedObjectTests {
|
||||
|
||||
elasticsearchTemplate.putMapping(Person.class);
|
||||
elasticsearchTemplate.bulkIndex(indexQueries);
|
||||
elasticsearchTemplate.refresh(Person.class, true);
|
||||
elasticsearchTemplate.refresh(Person.class);
|
||||
|
||||
final QueryBuilder builder = nestedQuery("books", boolQuery().must(termQuery("books.name", "java")));
|
||||
|
||||
@@ -372,7 +373,7 @@ public class NestedObjectTests {
|
||||
indexQueries.add(indexQuery2);
|
||||
//when
|
||||
elasticsearchTemplate.bulkIndex(indexQueries);
|
||||
elasticsearchTemplate.refresh(Book.class, true);
|
||||
elasticsearchTemplate.refresh(Book.class);
|
||||
//then
|
||||
final SearchQuery searchQuery = new NativeSearchQueryBuilder()
|
||||
.withQuery(nestedQuery("buckets", termQuery("buckets.1", "test3")))
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.elasticsearch;
|
||||
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.Version;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.ScriptedField;
|
||||
|
||||
/**
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
*/
|
||||
@Document(indexName = "test-index", type = "test-type", shards = 1, replicas = 0, refreshInterval = "-1")
|
||||
public class SampleEntity {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
private String type;
|
||||
private String message;
|
||||
private int rate;
|
||||
@ScriptedField
|
||||
private Long scriptedRate;
|
||||
private boolean available;
|
||||
private String highlightedMessage;
|
||||
@Version
|
||||
private Long version;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public int getRate() {
|
||||
return rate;
|
||||
}
|
||||
|
||||
public void setRate(int rate) {
|
||||
this.rate = rate;
|
||||
}
|
||||
|
||||
public Long getScriptedRate() {
|
||||
return scriptedRate;
|
||||
}
|
||||
|
||||
public void setScriptedRate(Long scriptedRate) {
|
||||
this.scriptedRate = scriptedRate;
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return available;
|
||||
}
|
||||
|
||||
public void setAvailable(boolean available) {
|
||||
this.available = available;
|
||||
}
|
||||
|
||||
public String getHighlightedMessage() {
|
||||
return highlightedMessage;
|
||||
}
|
||||
|
||||
public void setHighlightedMessage(String highlightedMessage) {
|
||||
this.highlightedMessage = highlightedMessage;
|
||||
}
|
||||
|
||||
public Long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(Long version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof SampleEntity)) {
|
||||
return false;
|
||||
}
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
SampleEntity rhs = (SampleEntity) obj;
|
||||
return new EqualsBuilder().append(this.id, rhs.id).append(this.type, rhs.type).append(this.message, rhs.message)
|
||||
.append(this.rate, rhs.rate).append(this.available, rhs.available).append(this.version, rhs.version).isEquals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder().append(id).append(type).append(message).append(rate).append(available).append(version)
|
||||
.toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SampleEntity{" +
|
||||
"id='" + id + '\'' +
|
||||
", type='" + type + '\'' +
|
||||
", message='" + message + '\'' +
|
||||
", rate=" + rate +
|
||||
", available=" + available +
|
||||
", highlightedMessage='" + highlightedMessage + '\'' +
|
||||
", version=" + version +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.elasticsearch;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.Version;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.ScriptedField;
|
||||
|
||||
/**
|
||||
* @author Gad Akuka
|
||||
*/
|
||||
@Document(indexName = "test-index", type = "test-type", indexStoreType = "memory", shards = 1, replicas = 0, refreshInterval = "-1")
|
||||
public class SampleEntityUUIDKeyed {
|
||||
|
||||
@Id
|
||||
private UUID id;
|
||||
private String type;
|
||||
private String message;
|
||||
private int rate;
|
||||
@ScriptedField
|
||||
private Long scriptedRate;
|
||||
private boolean available;
|
||||
private String highlightedMessage;
|
||||
@Version
|
||||
private Long version;
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public int getRate() {
|
||||
return rate;
|
||||
}
|
||||
|
||||
public void setRate(int rate) {
|
||||
this.rate = rate;
|
||||
}
|
||||
|
||||
public Long getScriptedRate() {
|
||||
return scriptedRate;
|
||||
}
|
||||
|
||||
public void setScriptedRate(Long scriptedRate) {
|
||||
this.scriptedRate = scriptedRate;
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return available;
|
||||
}
|
||||
|
||||
public void setAvailable(boolean available) {
|
||||
this.available = available;
|
||||
}
|
||||
|
||||
public String getHighlightedMessage() {
|
||||
return highlightedMessage;
|
||||
}
|
||||
|
||||
public void setHighlightedMessage(String highlightedMessage) {
|
||||
this.highlightedMessage = highlightedMessage;
|
||||
}
|
||||
|
||||
public Long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(Long version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof SampleEntityUUIDKeyed)) {
|
||||
return false;
|
||||
}
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
SampleEntityUUIDKeyed rhs = (SampleEntityUUIDKeyed) obj;
|
||||
return new EqualsBuilder().append(this.id, rhs.id).append(this.type, rhs.type).append(this.message, rhs.message)
|
||||
.append(this.rate, rhs.rate).append(this.available, rhs.available).append(this.version, rhs.version).isEquals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder().append(id).append(type).append(message).append(rate).append(available).append(version)
|
||||
.toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SampleEntity{" +
|
||||
"id='" + id + '\'' +
|
||||
", type='" + type + '\'' +
|
||||
", message='" + message + '\'' +
|
||||
", rate=" + rate +
|
||||
", available=" + available +
|
||||
", highlightedMessage='" + highlightedMessage + '\'' +
|
||||
", version=" + version +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import static org.junit.Assert.*;
|
||||
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -49,6 +50,7 @@ public class SpELEntityTests {
|
||||
repository.deleteAll();
|
||||
}
|
||||
|
||||
@Ignore("DATAES-211")
|
||||
@Test
|
||||
public void shouldDo() {
|
||||
// Given
|
||||
@@ -63,6 +65,7 @@ public class SpELEntityTests {
|
||||
assertThat(count, is(2L));
|
||||
}
|
||||
|
||||
@Ignore("DATAES-211")
|
||||
@Test
|
||||
public void shouldSupportSpelInType() {
|
||||
// Given
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.elasticsearch;
|
||||
|
||||
import static org.elasticsearch.node.NodeBuilder.*;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.elasticsearch.client.node.NodeClient;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
|
||||
/**
|
||||
* @author Mohsin Husen
|
||||
*/
|
||||
public class Utils {
|
||||
|
||||
public static NodeClient getNodeClient() {
|
||||
return (NodeClient) nodeBuilder().settings(Settings.builder()
|
||||
.put("http.enabled", "false")
|
||||
.put("path.data", "target/elasticsearchTestData")
|
||||
.put("path.home", "src/test/resources/test-home-dir"))
|
||||
.clusterName(UUID.randomUUID().toString()).local(true).node()
|
||||
.client();
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.builder;
|
||||
|
||||
import org.springframework.data.elasticsearch.core.query.IndexQuery;
|
||||
import org.springframework.data.elasticsearch.entities.SampleEntity;
|
||||
|
||||
/**
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Artur Konczak
|
||||
*/
|
||||
public class SampleEntityBuilder {
|
||||
|
||||
private SampleEntity result;
|
||||
|
||||
public SampleEntityBuilder(String id) {
|
||||
result = new SampleEntity();
|
||||
result.setId(id);
|
||||
}
|
||||
|
||||
public SampleEntityBuilder type(String type) {
|
||||
result.setType(type);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SampleEntityBuilder message(String message) {
|
||||
result.setMessage(message);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SampleEntityBuilder rate(int rate) {
|
||||
result.setRate(rate);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SampleEntityBuilder available(boolean available) {
|
||||
result.setAvailable(available);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SampleEntityBuilder highlightedMessage(String highlightedMessage) {
|
||||
result.setHighlightedMessage(highlightedMessage);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SampleEntityBuilder version(Long version) {
|
||||
result.setVersion(version);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SampleEntity build() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public IndexQuery buildIndex() {
|
||||
IndexQuery indexQuery = new IndexQuery();
|
||||
indexQuery.setId(result.getId());
|
||||
indexQuery.setObject(result);
|
||||
return indexQuery;
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.builder;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.springframework.data.elasticsearch.core.query.IndexQuery;
|
||||
import org.springframework.data.elasticsearch.entities.StockPrice;
|
||||
|
||||
/**
|
||||
* @author Artur Konczak
|
||||
* @author Mohsin Husen
|
||||
*/
|
||||
public class StockPriceBuilder {
|
||||
|
||||
private StockPrice result;
|
||||
|
||||
public StockPriceBuilder(String id) {
|
||||
result = new StockPrice(id);
|
||||
}
|
||||
|
||||
public StockPriceBuilder symbol(String symbol) {
|
||||
result.setSymbol(symbol);
|
||||
return this;
|
||||
}
|
||||
|
||||
public StockPriceBuilder price(BigDecimal price) {
|
||||
result.setPrice(price);
|
||||
return this;
|
||||
}
|
||||
|
||||
public StockPriceBuilder price(double price) {
|
||||
result.setPrice(new BigDecimal(price));
|
||||
return this;
|
||||
}
|
||||
|
||||
public StockPrice build() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public IndexQuery buildIndex() {
|
||||
IndexQuery indexQuery = new IndexQuery();
|
||||
indexQuery.setId(result.getId());
|
||||
indexQuery.setObject(result);
|
||||
return indexQuery;
|
||||
}
|
||||
}
|
||||
+100
-96
@@ -1,96 +1,100 @@
|
||||
/*
|
||||
* Copyright 2013-15 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.elasticsearch.node.NodeBuilder.*;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
|
||||
import org.springframework.data.elasticsearch.entities.SampleEntity;
|
||||
import org.springframework.data.elasticsearch.repositories.sample.SampleElasticsearchRepository;
|
||||
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
|
||||
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Kevin Leturc
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class EnableElasticsearchRepositoriesTests implements ApplicationContextAware {
|
||||
|
||||
ApplicationContext context;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.context = applicationContext;
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableElasticsearchRepositories(basePackages = {"org.springframework.data.elasticsearch.repositories.sample",
|
||||
"org.springframework.data.elasticsearch.config"})
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
public ElasticsearchOperations elasticsearchTemplate() {
|
||||
return new ElasticsearchTemplate(nodeBuilder().local(true).clusterName("testCluster2").node().client());
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private SampleElasticsearchRepository repository;
|
||||
|
||||
@Autowired(required = false)
|
||||
private SampleRepository nestedRepository;
|
||||
|
||||
interface SampleRepository extends Repository<SampleEntity, Long> {};
|
||||
|
||||
@Test
|
||||
public void bootstrapsRepository() {
|
||||
assertThat(repository, is(notNullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldScanSelectedPackage() {
|
||||
//given
|
||||
|
||||
//when
|
||||
String[] beanNamesForType = context.getBeanNamesForType(ElasticsearchRepository.class);
|
||||
|
||||
//then
|
||||
assertThat(beanNamesForType.length, is(1));
|
||||
assertThat(beanNamesForType[0], is("sampleElasticsearchRepository"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasNotNestedRepository() {
|
||||
assertNull(nestedRepository);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2013-15 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.junit.Assert.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.elasticsearch.Utils;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
|
||||
import org.springframework.data.elasticsearch.entities.SampleEntity;
|
||||
import org.springframework.data.elasticsearch.repositories.sample.SampleElasticsearchRepository;
|
||||
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
|
||||
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Kevin Leturc
|
||||
* @author Gad Akuka
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class EnableElasticsearchRepositoriesTests implements ApplicationContextAware {
|
||||
|
||||
ApplicationContext context;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.context = applicationContext;
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableElasticsearchRepositories(basePackages = {"org.springframework.data.elasticsearch.repositories.sample",
|
||||
"org.springframework.data.elasticsearch.config"})
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
public ElasticsearchOperations elasticsearchTemplate() {
|
||||
return new ElasticsearchTemplate(Utils.getNodeClient());
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private SampleElasticsearchRepository repository;
|
||||
|
||||
@Autowired(required = false)
|
||||
private SampleRepository nestedRepository;
|
||||
|
||||
interface SampleRepository extends Repository<SampleEntity, Long> {};
|
||||
|
||||
@Test
|
||||
public void bootstrapsRepository() {
|
||||
assertThat(repository, is(notNullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldScanSelectedPackage() {
|
||||
//given
|
||||
|
||||
//when
|
||||
String[] beanNamesForType = context.getBeanNamesForType(ElasticsearchRepository.class);
|
||||
|
||||
//then
|
||||
assertThat(beanNamesForType.length, is(2));
|
||||
assertTrue(Arrays.asList(beanNamesForType).contains("sampleElasticsearchRepository"));
|
||||
assertTrue(Arrays.asList(beanNamesForType).contains("sampleUUIDKeyedElasticsearchRepository"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasNotNestedRepository() {
|
||||
assertNull(nestedRepository);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -20,6 +20,7 @@ import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.elasticsearch.Utils;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
|
||||
import org.springframework.data.elasticsearch.entities.SampleEntity;
|
||||
@@ -28,7 +29,6 @@ import org.springframework.data.repository.Repository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import static org.elasticsearch.node.NodeBuilder.nodeBuilder;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
@@ -45,7 +45,7 @@ public class EnableNestedElasticsearchRepositoriesTests {
|
||||
|
||||
@Bean
|
||||
public ElasticsearchOperations elasticsearchTemplate() {
|
||||
return new ElasticsearchTemplate(nodeBuilder().local(true).clusterName("testCluster2").node().client());
|
||||
return new ElasticsearchTemplate(Utils.getNodeClient());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,16 +19,14 @@ import static org.apache.commons.lang.RandomStringUtils.*;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.elasticsearch.cluster.metadata.AliasMetaData;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.elasticsearch.builder.SampleEntityBuilder;
|
||||
import org.springframework.data.elasticsearch.core.query.*;
|
||||
import org.springframework.data.elasticsearch.entities.SampleEntity;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
@@ -41,7 +39,8 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
@ContextConfiguration("classpath:elasticsearch-template-test.xml")
|
||||
public class AliasTests {
|
||||
|
||||
private static final String INDEX_NAME = "test-alias-index";
|
||||
private static final String INDEX_NAME_1 = "test-alias-index-1";
|
||||
private static final String INDEX_NAME_2 = "test-alias-index-2";
|
||||
private static final String TYPE_NAME = "test-alias-type";
|
||||
|
||||
@Autowired
|
||||
@@ -53,11 +52,15 @@ public class AliasTests {
|
||||
settings.put("index.refresh_interval", "-1");
|
||||
settings.put("index.number_of_replicas", "0");
|
||||
settings.put("index.number_of_shards", "2");
|
||||
settings.put("index.store.type", "memory");
|
||||
settings.put("index.store.type", "fs");
|
||||
|
||||
elasticsearchTemplate.deleteIndex(INDEX_NAME);
|
||||
elasticsearchTemplate.createIndex(INDEX_NAME, settings);
|
||||
elasticsearchTemplate.refresh(INDEX_NAME, true);
|
||||
elasticsearchTemplate.deleteIndex(INDEX_NAME_1);
|
||||
elasticsearchTemplate.createIndex(INDEX_NAME_1, settings);
|
||||
elasticsearchTemplate.refresh(INDEX_NAME_1);
|
||||
|
||||
elasticsearchTemplate.deleteIndex(INDEX_NAME_2);
|
||||
elasticsearchTemplate.createIndex(INDEX_NAME_2, settings);
|
||||
elasticsearchTemplate.refresh(INDEX_NAME_2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -65,34 +68,33 @@ public class AliasTests {
|
||||
// given
|
||||
String aliasName = "test-alias";
|
||||
AliasQuery aliasQuery = new AliasBuilder()
|
||||
.withIndexName(INDEX_NAME)
|
||||
.withIndexName(INDEX_NAME_1)
|
||||
.withAliasName(aliasName).build();
|
||||
// when
|
||||
elasticsearchTemplate.addAlias(aliasQuery);
|
||||
// then
|
||||
Set<String> aliases = elasticsearchTemplate.queryForAlias(INDEX_NAME);
|
||||
List<AliasMetaData> aliases = elasticsearchTemplate.queryForAlias(INDEX_NAME_1);
|
||||
assertThat(aliases, is(notNullValue()));
|
||||
assertThat(aliases.contains(aliasName), is(true));
|
||||
assertThat(aliases.get(0).alias(), is(aliasName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRemoveAlias() {
|
||||
// given
|
||||
String indexName = INDEX_NAME;
|
||||
String indexName = INDEX_NAME_1;
|
||||
String aliasName = "test-alias";
|
||||
AliasQuery aliasQuery = new AliasBuilder()
|
||||
.withIndexName(indexName)
|
||||
.withAliasName(aliasName).build();
|
||||
// when
|
||||
elasticsearchTemplate.addAlias(aliasQuery);
|
||||
Set<String> aliases = elasticsearchTemplate.queryForAlias(indexName);
|
||||
List<AliasMetaData> aliases = elasticsearchTemplate.queryForAlias(indexName);
|
||||
assertThat(aliases, is(notNullValue()));
|
||||
assertThat(aliases.contains(aliasName), is(true));
|
||||
assertThat(aliases.get(0).alias(), is(aliasName));
|
||||
// then
|
||||
elasticsearchTemplate.removeAlias(aliasQuery);
|
||||
aliases = elasticsearchTemplate.queryForAlias(indexName);
|
||||
assertThat(aliases, is(notNullValue()));
|
||||
assertThat(aliases.size(), is(0));
|
||||
assertThat(aliases, is(nullValue()));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -101,7 +103,7 @@ public class AliasTests {
|
||||
@Test
|
||||
public void shouldAddAliasWithGivenRoutingValue() {
|
||||
//given
|
||||
String indexName = INDEX_NAME;
|
||||
String indexName = INDEX_NAME_1;
|
||||
String alias = "test-alias";
|
||||
|
||||
AliasQuery aliasQuery = new AliasBuilder()
|
||||
@@ -113,7 +115,7 @@ public class AliasTests {
|
||||
elasticsearchTemplate.addAlias(aliasQuery);
|
||||
|
||||
String documentId = randomNumeric(5);
|
||||
SampleEntity sampleEntity = new SampleEntityBuilder(documentId)
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId)
|
||||
.message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -125,15 +127,17 @@ public class AliasTests {
|
||||
.build();
|
||||
|
||||
elasticsearchTemplate.index(indexQuery);
|
||||
elasticsearchTemplate.refresh(INDEX_NAME, true);
|
||||
elasticsearchTemplate.refresh(INDEX_NAME_1);
|
||||
|
||||
SearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
||||
.withIndices(alias).withTypes(TYPE_NAME).build();
|
||||
long count = elasticsearchTemplate.count(query);
|
||||
//then
|
||||
Set<String> aliases = elasticsearchTemplate.queryForAlias(INDEX_NAME);
|
||||
List<AliasMetaData> aliases = elasticsearchTemplate.queryForAlias(INDEX_NAME_1);
|
||||
assertThat(aliases, is(notNullValue()));
|
||||
assertThat(aliases.contains(alias), is(true));
|
||||
assertThat(aliases.get(0).alias(), is(alias));
|
||||
assertThat(aliases.get(0).searchRouting(), is("0"));
|
||||
assertThat(aliases.get(0).indexRouting(), is("0"));
|
||||
assertThat(count, is(1L));
|
||||
|
||||
//cleanup
|
||||
@@ -141,7 +145,7 @@ public class AliasTests {
|
||||
elasticsearchTemplate.deleteIndex(SampleEntity.class);
|
||||
elasticsearchTemplate.createIndex(SampleEntity.class);
|
||||
elasticsearchTemplate.putMapping(SampleEntity.class);
|
||||
elasticsearchTemplate.refresh(SampleEntity.class, true);
|
||||
elasticsearchTemplate.refresh(SampleEntity.class);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -154,12 +158,12 @@ public class AliasTests {
|
||||
String alias2 = "test-alias-2";
|
||||
|
||||
AliasQuery aliasQuery1 = new AliasBuilder()
|
||||
.withIndexName(INDEX_NAME)
|
||||
.withIndexName(INDEX_NAME_1)
|
||||
.withAliasName(alias1)
|
||||
.withIndexRouting("0").build();
|
||||
|
||||
AliasQuery aliasQuery2 = new AliasBuilder()
|
||||
.withIndexName(INDEX_NAME)
|
||||
.withIndexName(INDEX_NAME_2)
|
||||
.withAliasName(alias2)
|
||||
.withSearchRouting("1").build();
|
||||
|
||||
@@ -168,7 +172,7 @@ public class AliasTests {
|
||||
elasticsearchTemplate.addAlias(aliasQuery2);
|
||||
|
||||
String documentId = randomNumeric(5);
|
||||
SampleEntity sampleEntity = new SampleEntityBuilder(documentId)
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(documentId)
|
||||
.message("some message")
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
@@ -179,24 +183,21 @@ public class AliasTests {
|
||||
.withObject(sampleEntity).build();
|
||||
|
||||
elasticsearchTemplate.index(indexQuery);
|
||||
elasticsearchTemplate.refresh(SampleEntity.class, true);
|
||||
|
||||
SearchQuery query = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
||||
.withIndices(alias2).withTypes(TYPE_NAME).build();
|
||||
long count = elasticsearchTemplate.count(query, SampleEntity.class);
|
||||
|
||||
// then
|
||||
Set<String> aliases = elasticsearchTemplate.queryForAlias(INDEX_NAME);
|
||||
assertThat(aliases, is(notNullValue()));
|
||||
assertThat(aliases.contains(alias1), is(true));
|
||||
assertThat(aliases.contains(alias2), is(true));
|
||||
assertThat(count, is(0L));
|
||||
List<AliasMetaData> responseAlias1 = elasticsearchTemplate.queryForAlias(INDEX_NAME_1);
|
||||
assertThat(responseAlias1, is(notNullValue()));
|
||||
assertThat(responseAlias1.get(0).alias(), is(alias1));
|
||||
assertThat(responseAlias1.get(0).indexRouting(), is("0"));
|
||||
|
||||
List<AliasMetaData> responseAlias2 = elasticsearchTemplate.queryForAlias(INDEX_NAME_2);
|
||||
assertThat(responseAlias2, is(notNullValue()));
|
||||
assertThat(responseAlias2.get(0).alias(), is(alias2));
|
||||
assertThat(responseAlias2.get(0).searchRouting(), is("1"));
|
||||
|
||||
//cleanup
|
||||
elasticsearchTemplate.removeAlias(aliasQuery1);
|
||||
elasticsearchTemplate.removeAlias(aliasQuery2);
|
||||
elasticsearchTemplate.deleteIndex(SampleEntity.class);
|
||||
elasticsearchTemplate.createIndex(SampleEntity.class);
|
||||
elasticsearchTemplate.putMapping(SampleEntity.class);
|
||||
elasticsearchTemplate.refresh(SampleEntity.class, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,9 @@ 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;
|
||||
|
||||
/**
|
||||
* @author Artur Konczak
|
||||
@@ -46,7 +48,7 @@ public class CustomResultMapper implements ResultsMapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> FacetedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
|
||||
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user