文章来源: http://www.cnblogs.com/guozp/p/8686904.html

一 elasticsearch基础

  这里假设各位已经简单了解过elasticsearch,并不对es进入更多的,更深层次的解释,如有必要,会在写文章专门进行es讲解。

  Elasticsearch是一个基于Apache Lucene(TM)的开源搜索引擎。无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。

  但是,Lucene只是一个库。想要使用它,你必须使用Java来作为开发语言并将其直接集成到你的应用中,更糟糕的是,Lucene非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的。

  Elasticsearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。

  index ==》索引 ==》Mysql中的一个库,库里面可以建立很多表,存储不同类型的数据,而表在ES中就是type。

   type ==》类型 ==》相当于Mysql中的一张表,存储json类型的数据

   document  ==》文档 ==》一个文档相当于Mysql一行的数据

   field ==》列 ==》相当于mysql中的列,也就是一个属性

这里多说下:

在Elasticsearch6.0.0或者或者更新版本中创建的索引只会包含一个映射类型(mappingtype)。在5.x中创建的具有多个映射类型的索引在Elasticsearch6.x中依然会正常工作。在Elasticsearch7.0.0中,映射类型type将会被完全移除。

原文链接

  开始的时候,我们说“索引(index)”类似于SQL数据库中的“数据库”,将“类型(type)”等同于“表”。

  这是一个糟糕的类比,并且导致了一些错误的假设。在SQL数据库中,表之间是相互独立的。一个表中的各列并不会影响到其它表中的同名的列。而在映射类型(mappingtype)中却不是这样的。

  在同一个Elasticsearch索引中,其中不同映射类型中的同名字段在内部是由同一个Lucene字段来支持的。换句话说,使用上面的例子,user类型中的user_name字段与tweet类型中的user_name字段是完全一样的,并且两个user_name字段在两个类型中必须具有相同的映射(定义)。

  这会在某些情况下导致一些混乱,比如,在同一个索引中,当你想在其中的一个类型中将deleted字段作为date类型,而在另一个类型中将其作为boolean字段。

  在此之上需要考虑一点,如果同一个索引中存储的各个实体如果只有很少或者根本没有同样的字段,这种情况会导致稀疏数据,并且会影响到Lucene的高效压缩数据的能力。

  基于这些原因,将映射类型的概念从Elasticsearch中移除。

二 springboot 对应的Es版本关系

springboot  elasticsearch
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

  1、None of the configured nodes are available 或者org.elasticsearch.transport.RemoteTransportException: Failed to deserialize exception response from stream

  原因:spring data elasticSearch 的版本与Spring boot、Elasticsearch版本不匹配。

这是版本之间的对应关系。Spring boot 1.3.5默认的elasticsearch版本是1.5.2,此时启动1.7.2版本以下的Elasticsearch客户端连接正常。

  注:注意java的es默认连接端口是9300,9200是http端口,这两个在使用中应注意区分。

  2、Caused by: java.lang.IllegalArgumentException: @ConditionalOnMissingBean annotations must specify at least one bean (type, name or annotation)

  原因:spring boot是1.3.x版本,而es采用了2.x版本。在es的2.x版本去除了一些类,而这些类在spring boot的1.3.x版本中仍然被使用,导致此错误

    以上解决参考下面的对应关系

Spring Boot Version (x) Spring Data Elasticsearch Version (y) Elasticsearch Version (z)
x <= 1.3.5 y <= 1.3.4 z <= 1.7.2*
x >= 1.4.x 2.0.0 <=y < 5.0.0** 2.0.0 <= z < 5.0.0**

   请一定注意版本兼容问题。这关系到很多maven依赖。Spring Data Elasticsearch Spring Boot version matrix

ik 分词对应的版本关系:

  elasticsearch-analysis-ik

Analyzer:

   ik_smart , ik_max_word , Tokenizer: ik_smart , ik_max_word

Versions

IK version ES version
master 6.x -> master
6.2.2 6.2.2
6.1.3 6.1.3
5.6.8 5.6.8
5.5.3 5.5.3
5.4.3 5.4.3
5.3.3 5.3.3
5.2.2 5.2.2
5.1.2 5.1.2
1.10.6 2.4.6
1.9.5 2.3.5
1.8.1 2.2.1
1.7.0 2.1.1
1.5.0 2.0.0
1.2.6 1.0.0
1.2.5 0.90.x
1.1.3 0.20.x
1.0.0 0.16.2 -> 0.19.0

三 环境构建

maven依赖:前提是依赖

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

配置文件:

# ES
#开启 Elasticsearch 仓库(默认值:true)
spring.data.elasticsearch.repositories.enabled=true
#默认 9300 是 Java 客户端的端口。9200 是支持 Restful HTTP 的接口
spring.data.elasticsearch.cluster-nodes = 127.0.0.1:9300
#spring.data.elasticsearch.cluster-name Elasticsearch 集群名(默认值: elasticsearch)
#spring.data.elasticsearch.cluster-nodes 集群节点地址列表,用逗号分隔。如果没有指定,就启动一个客户端节点
#spring.data.elasticsearch.propertie 用来配置客户端的额外属性
#存储索引的位置
spring.data.elasticsearch.properties.path.home=/data/project/target/elastic
#连接超时的时间
spring.data.elasticsearch.properties.transport.tcp.connect_timeout=120s

  

四 es索引实体类

Spring-data-elasticsearch为我们提供了@Document@Field等注解,如果某个实体需要建立索引,只需要加上这些注解即可

1.类上注解:@Document (相当于Hibernate实体的@Entity/@Table)(必写),加上了@Document注解之后,默认情况下这个实体中所有的属性都会被建立索引、并且分词。

类型 属性名 默认值 说明
String indexName 索引库的名称,建议以项目的名称命名
String type “” 类型,建议以实体的名称命名
short shards 5 默认分区数
short replica 1 每个分区默认的备份数
String refreshInterval “1s” 刷新间隔
String indexStoreType “fs” 索引文件存储类型

2.主键注解:@Id (相当于Hibernate实体的主键@Id注解)(必写)

只是一个标识,并没有属性。

3.属性注解 @Field (相当于Hibernate实体的@Column注解)

@Field默认是可以不加的,默认所有属性都会添加到ES中。加上@Field之后,@document默认把所有字段加上索引失效,只有家@Field 才会被索引(同时也看设置索引的属性是否为no)

类型 属性名 默认值 说明
FieldType type FieldType.Auto 自动检测属性的类型
FieldIndex index FieldIndex.analyzed 默认情况下分词
boolean store false 默认情况下不存储原文
String searchAnalyzer “” 指定字段搜索时使用的分词器
String indexAnalyzer “” 指定字段建立索引时指定的分词器
String[] ignoreFields {} 如果某个字段需要被忽略

五 相关查询方法

官网参考

  实现方式比较多,已经存在的接口,使用根据需要继承即可:

  1、CrudRepository接口 

public interface CrudRepository<T, ID extends Serializable>
extends Repository<T, ID> { <S extends T> S save(S entity); Optional<T> findById(ID primaryKey); Iterable<T> findAll(); long count(); void delete(T entity); boolean existsById(ID primaryKey); // … more functionality omitted.
}

  2、PagingAndSortingRepository接口

public interface PagingAndSortingRepository<T, ID extends Serializable>
extends CrudRepository<T, ID> { Iterable<T> findAll(Sort sort); Page<T> findAll(Pageable pageable);
}

例子:

分页:

PagingAndSortingRepository<User, Long> repository = // … get access to a bean
Page<User> users = repository.findAll(new PageRequest(1, 20));

计数:

interface UserRepository extends CrudRepository<User, Long> {

  long countByLastname(String lastname);
}  

  3、其他,参考官网

  

  自定义查询实现

那么我们如何自定义方法呢?我们只要使用特定的单词对方法名进行定义,那么Spring就会对我们写的方法名进行解析, 

该机制条前缀find…Byread…Byquery…Bycount…By,和get…By从所述方法和开始分析它的其余部分。引入子句可以包含进一步的表达式,如Distinct在要创建的查询上设置不同的标志。然而,第一个By作为分隔符来指示实际标准的开始。在非常基础的层次上,您可以定义实体属性的条件并将它们与And和连接起来Or

interface PersonRepository extends Repository<User, Long> {

  List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname);

  // Enables the distinct flag for the query
List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname);
List<Person> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname); // Enabling ignoring case for an individual property
List<Person> findByLastnameIgnoreCase(String lastname);
// Enabling ignoring case for all suitable properties
List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname); // Enabling static ORDER BY for a query
List<Person> findByLastnameOrderByFirstnameAsc(String lastname);
List<Person> findByLastnameOrderByFirstnameDesc(String lastname);
}

  构建查询属性算法原理

如上例所示。在查询创建时,确保解析的属性是托管类的属性。但是,你也可以通过遍历嵌套属性来定义约束。假设Person x有一个Address和 ZipCode。在这种情况下,方法名称为

List<Person> findByAddressZipCode(ZipCode zipCode);

创建属性遍历x.address.zipCode。解析算法首先将整个part(AddressZipCode)作为属性进行解释,然后检查具有该名称属性的类。如果皮匹配成功,则使用该属性。如果不是属性,则算法拆分从右侧的驼峰部分头部和尾部,并试图找出相应的属性,在我们的例子,AddressZipCode。如果算法找到具有该头部的属性,它将采用尾部并继续从那里构建树,然后按照刚刚描述的方式分割尾部。如果第一个分割不匹配,则算法将分割点移动到左侧(AddressZipCode)并继续。

虽然这应该适用于大多数情况,但算法仍可能会选择错误的属性。假设这个Person类也有一个addressZip属性。该算法将在第一轮拆分中匹配,并且基本上选择错误的属性并最终失败(因为addressZip可能没有code属性的类型)。

为了解决这个歧义,你可以\_在你的方法名称中使用手动定义遍历点。所以我们的方法名称会像这样结束:

List<Person> findByAddress_ZipCode(ZipCode zipCode);
由于我们将下划线视为保留字符,因此我们强烈建议遵循标准的Java命名约定(即,不要在属性名称中使用下划线,而应使用驼峰大小写)

其他分页查询

Page<User> findByLastname(String lastname, Pageable pageable);

Slice<User> findByLastname(String lastname, Pageable pageable);

List<User> findByLastname(String lastname, Sort sort);

  也可以用Java8 Stream查询和sql语句查询


@Query("select u from User u")
Stream<User> findAllByCustomQueryAndStream(); Stream<User> readAllByFirstnameNotNull(); @Query("select u from User u")
Stream<User> streamAllPaged(Pageable pageable);

  有些在复杂的可以使用es查询语句

  我们可以使用@Query注解进行查询,这样要求我们需要自己写ES的查询语句

  
public interface BookRepository extends ElasticsearchRepository<Book, String> {
@Query("{"bool" : {"must" : {"field" : {"name" : "?0"}}}}")
Page<Book> findByName(String name,Pageable pageable);
}

方法和es查询转换:


Keyword Sample Elasticsearch Query String

And

findByNameAndPrice

{"bool" : {"must" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}

Or

findByNameOrPrice

{"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}

Is

findByName

{"bool" : {"must" : {"field" : {"name" : "?"}}}}

Not

findByNameNot

{"bool" : {"must_not" : {"field" : {"name" : "?"}}}}

Between

findByPriceBetween

{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}

LessThanEqual

findByPriceLessThan

{"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}

GreaterThanEqual

findByPriceGreaterThan

{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}

Before

findByPriceBefore

{"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}

After

findByPriceAfter

{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}

Like

findByNameLike

{"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}

StartingWith

findByNameStartingWith

{"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}

EndingWith

findByNameEndingWith

{"bool" : {"must" : {"field" : {"name" : {"query" : "*?","analyze_wildcard" : true}}}}}

Contains/Containing

findByNameContaining

{"bool" : {"must" : {"field" : {"name" : {"query" : "?","analyze_wildcard" : true}}}}}

In

findByNameIn(Collection<String>names)

{"bool" : {"must" : {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"name" : "?"}} ]}}}}

NotIn

findByNameNotIn(Collection<String>names)

{"bool" : {"must_not" : {"bool" : {"should" : {"field" : {"name" : "?"}}}}}}

Near

findByStoreNear

Not Supported Yet !

True

findByAvailableTrue

{"bool" : {"must" : {"field" : {"available" : true}}}}

False

findByAvailableFalse

{"bool" : {"must" : {"field" : {"available" : false}}}}

OrderBy

findByAvailableTrueOrderByNameDesc

{"sort" : [{ "name" : {"order" : "desc"} }],"bool" : {"must" : {"field" : {"available" : true}}}}

 

六 between使用注意

在使用的时候没有找到直接的例子,由于between是转换成range,所以需要范围参数from和to,

举例如下:

Page<Recruit> findByRecruitWorkAndRecruitCitysAndWorkTypeAndXjTimeBetween(String recruitWork, String recruitCitys, Integer workType, Date fromXjTime, Date toXjTime,Pageable pageable);

  注意:

  这里必须要注意的是:只要使用了between参数,****XjTimeBetween(......,from,to) ,使用该方法的时候,必须要传递范围参数from,to,不能同时为空。

  否则异常

 

org.springframework.dao.InvalidDataAccessApiUsageException: Range [* TO *] is not allowed
at org.springframework.data.elasticsearch.core.query.Criteria.between(Criteria.java:304)
at org.springframework.data.elasticsearch.repository.query.parser.ElasticsearchQueryCreator.from(ElasticsearchQueryCreator.java:127)
at org.springframework.data.elasticsearch.repository.query.parser.ElasticsearchQueryCreator.and(ElasticsearchQueryCreator.java:76)
at org.springframework.data.elasticsearch.repository.query.parser.ElasticsearchQueryCreator.and(ElasticsearchQueryCreator.java:46)
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createCriteria(AbstractQueryCreator.java:109)
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:88)
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:73)
at org.springframework.data.elasticsearch.repository.query.ElasticsearchPartQuery.createQuery(ElasticsearchPartQuery.java:102)
at org.springframework.data.elasticsearch.repository.query.ElasticsearchPartQuery.execute(ElasticsearchPartQuery.java:51)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:499)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:477)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:56)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy86.findByRecruitWorkAndRecruitCitysAndWorkTypeAndXjTimeBetween(Unknown Source)
at com.zhimingdeng.service.impl.EsIndexServiceImpl.findByRecruitWorkAndRecruitCitysAndWorkTypeAndXjTimeBetween(EsIndexServiceImpl.java:155)

  因为底层要求参数不能同时为空

七  es时间类型注意

  来源: http://www.cnblogs.com/guozp/p/8686904.html

   对于Elasticsearch原生支持date类型,json格式通过字符来表示date类型。所以在用json提交日期至elasticsearch的时候,es会隐式转换,把es认为是date类型的字符串直接转为date类型,间字段内容实际上就是转换成long类型作为内部存储的(所以完全可以接受其他时间格式作为时间字段的内容)。至于什么样的字符串es会认为可以转换成date类型,参考elasticsearch官网介绍

  date类型是包含时区信息的,如果我们没有在json代表日期的字符串中显式指定时区,对es来说没什么问题,但是对于我们来说可能会发现一些时间差8个小时的问题。

  Elastic本身有一种特殊的时间格式,其形式如"2016-01-25T00:00:00",此格式为ISO8601标准。具体时间日期格式要求可以参见es官方文档

  然而我们在计算日期间隔,甚至按日分类的时候,往往需要把这个String时间转化为Unix时间戳(Unix Timestamp(时间戳))的形式,再进行计算。而通常,这个时间戳会以毫秒的形式(Java)保存在一个long类型里面,这就涉及到了String与long类型的相互转化。

  此外在使用Java Client聚合查询日期的时候,需要注意时区问题,因为默认的es是按照UTC标准时区算的,所以不设置的聚合统计结果是不正确的。默认不设置时区参数,es是安装UTC的时间进行查询的,所以分组的结果可能与预期不一样。  

  JSON 没有日期类型,因此在 Elasticsearch 中可以表达成:

  1. 日期格式化的字符串,比如: "2018-01-01" 或者 "2018/01/01 01:01:30";
  2. 毫秒级别的 long 类型或秒级别的 integer 类型,比如: 1515150699465, 1515150699;

  实际上不管日期以何种格式写入,在 ES 内部都会先穿换成 UTC 时间并存储为 long 类型。日期格式可以自定义,如果没有指定的话会使用以下的默认格式:

  "strict_date_optional_time||epoch_millis"

  因此总结来说,不管哪种可以表示时间的格式写入,都可以用来表示时间

  所以这里引出多种解决方案:

   1、es 默认的是 utc 时间,而国内服务器是 cst 时间,首先有时间上的差距需要转换。但是如果底层以及上层都统一用时间戳,完美解决时区问题。但是时间戳对我们来说不直观

  2、我们在往es提交日期数据的时候,直接提交带有时区信息的日期字符串,如:“2016-07-15T12:58:17.136+0800”

  3、还有另外的一种:   

 直接设置format为你想要的格式,比如 "yyyy-MM-dd HH:mm:ss" 然后存储的时候,指定格式,并且Mapping  也是指定相同的format 。

  第一次使用方式:
  
 @Field( type = FieldType.Date,
format = DateFormat.custom,pattern = date_optional_time"
)
private Date gmtCreate;

  

我这里是数据是从数据库直接读取,使用的datetime类型,原来直接使用的时候,抛异常:

  MapperParsingException[failed to parse [***]]; nested: IllegalArgumentException[Invalid format: "格式"];

  原因是: jackson库在转换为json的时候,将Date类型转为为了long型的字符串表示,而我们定义的是date_optional_time格式的字符串,所以解析错误,

  具体的解决办法:去掉注解中的format=DateFormat.date_optional_time,让其使用默认的格式,也就是 'strict_date_optional_time||epoch_millis' , 既能接受        date_optional_time格式的,也能接受epoch_millis格式,由于为了查看更直观感受改为如下:

  @Field( type = FieldType.Date,
format = DateFormat.custom,pattern = "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
)
private Date gmtCreate;

   改成这样后,底层多种格式都可以存储,如果没有根据时间进行范围查找,这里基本上已经就告一段落了。

    
    时间范围查找需求:存储Date,和取出来也是Date

    存储的时候利用各种JSON对象,如 Jackson 等。存储的时候就可以用JSON Format一下再存储,然后取出来后

  @Field( type = FieldType.Date,
format = DateFormat.custom,pattern = "yyyy-MM-dd HH:mm:ss"
)
@JsonFormat (shape = JsonFormat.Shape.STRING, pattern ="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date xjTime;

    有了这个注解后,

    timezone="GMT+8" 主要是因为底层存放的数据日期时区是UTC,这里转换成GMT
    真实存储格式如下(高能瞎眼):

    时间范围查找需求注意:

    根据条件查询的时候,时间范围需要传入range,这里涉及到了两种选择,底层查询方法实现的时候range的参数为

    1 date:

      传入的是date参数,然后就行查询的时候,会报异常,因为我把日期转成了yyyy-MM-dd HH:mm:ss,但是底层数据是2018-03-27T16:00:00.000Z这种格式,导致错误,详细异常如下

org.elasticsearch.action.search.SearchPhaseExecutionException: all shards failed
at org.elasticsearch.action.search.AbstractSearchAsyncAction.onFirstPhaseResult(AbstractSearchAsyncAction.java:206)
at org.elasticsearch.action.search.AbstractSearchAsyncAction$1.onFailure(AbstractSearchAsyncAction.java:152)
at org.elasticsearch.action.ActionListenerResponseHandler.handleException(ActionListenerResponseHandler.java:46)
at org.elasticsearch.transport.TransportService$DirectResponseChannel.processException(TransportService.java:855)
at org.elasticsearch.transport.TransportService$DirectResponseChannel.sendResponse(TransportService.java:833)
at org.elasticsearch.transport.TransportService$4.onFailure(TransportService.java:387)
at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:39)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.elasticsearch.ElasticsearchParseException: failed to parse date field [2018-03-27T16:00:00.000Z] with format [yyyy-MM-dd HH:mm:ss]
at org.elasticsearch.common.joda.DateMathParser.parseDateTime(DateMathParser.java:203)
at org.elasticsearch.common.joda.DateMathParser.parse(DateMathParser.java:67)
at org.elasticsearch.index.mapper.core.DateFieldMapper$DateFieldType.parseToMilliseconds(DateFieldMapper.java:451)
at org.elasticsearch.index.mapper.core.DateFieldMapper$DateFieldType.innerRangeQuery(DateFieldMapper.java:435)
at org.elasticsearch.index.mapper.core.DateFieldMapper$DateFieldType.access$000(DateFieldMapper.java:199)
at org.elasticsearch.index.mapper.core.DateFieldMapper$DateFieldType$LateParsingQuery.rewrite(DateFieldMapper.java:224)
at org.apache.lucene.search.BooleanQuery.rewrite(BooleanQuery.java:278)
at org.apache.lucene.search.IndexSearcher.rewrite(IndexSearcher.java:837)
at org.elasticsearch.search.internal.ContextIndexSearcher.rewrite(ContextIndexSearcher.java:81)
at org.elasticsearch.search.internal.DefaultSearchContext.preProcess(DefaultSearchContext.java:231)
at org.elasticsearch.search.query.QueryPhase.preProcess(QueryPhase.java:103)
at org.elasticsearch.search.SearchService.createContext(SearchService.java:676)
at org.elasticsearch.search.SearchService.createAndPutContext(SearchService.java:620)
at org.elasticsearch.search.SearchService.executeDfsPhase(SearchService.java:264)
at org.elasticsearch.search.action.SearchServiceTransportAction$SearchDfsTransportHandler.messageReceived(SearchServiceTransportAction.java:360)
at org.elasticsearch.search.action.SearchServiceTransportAction$SearchDfsTransportHandler.messageReceived(SearchServiceTransportAction.java:357)
at org.elasticsearch.transport.TransportRequestHandler.messageReceived(TransportRequestHandler.java:33)
at org.elasticsearch.transport.RequestHandlerRegistry.processMessageReceived(RequestHandlerRegistry.java:75)
at org.elasticsearch.transport.TransportService$4.doRun(TransportService.java:376)
at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37)
... 3 common frames omitted
Caused by: java.lang.IllegalArgumentException: Invalid format: "2018-03-27T16:00:00.000Z" is malformed at "T16:00:00.000Z"
at org.joda.time.format.DateTimeParserBucket.doParseMillis(DateTimeParserBucket.java:187)
at org.joda.time.format.DateTimeFormatter.parseMillis(DateTimeFormatter.java:826)
at org.elasticsearch.common.joda.DateMathParser.parseDateTime(DateMathParser.java:200)
... 22 common frames omitted

解决:

  传入的date参数格式化成底层的类型  

实现参考:

Page<Recruit> findByRecruitWorkAndRecruitCitysAndWorkTypeAndXjTimeBetween(String recruitWork, String recruitCitys, Integer workType, Date fromXjTime, Date toXjTime,Pageable pageable);

   

 2 String

    参数直接使用string,避免上层转换成不合适的时间格式,使用框架底层自己转换,避免错误。

  实现参考:

  

实现参考:
Page<Recruit> findByRecruitWorkAndRecruitCitysAndWorkTypeAndXjTimeBetween(String recruitWork, String recruitCitys, Integer workType, String fromXjTime, String toXjTime,Pageable pageable);

    

es时间自定义类型

https://stackoverflow.com/questions/29122071/elasticsearch-failed-to-parse-date

https://stackoverflow.com/questions/29496081/spring-data-elasticsearchs-field-annotation-not-working

https://stackoverflow.com/questions/32042430/elasticsearch-spring-data-date-format-always-is-long

八 使用注意

  个人认为springboot 这种集成es的方法,最大的优点是开发速度快,不要求对es一些api要求熟悉,能快速上手,即使之前对es不胜了解,也能通过方法名或者sql快速写出自己需要的逻辑,而具体转换成api层的操作,则有框架底层帮你实现。

  缺点也显而易见首先,使用的springboot的版本对es的版本也有了要求,不能超过es的某些版本号,部署时需要注意。第二,速度提升的同时,也失去了一些实用api的灵活性。一些比较灵活的条件封装不能很容易的实现。各有利弊,各位权衡

  来源: http://www.cnblogs.com/guozp/p/8686904.html

springboot elasticsearch 集成注意事项的更多相关文章

  1. springboot集成elk 一: springboot + Elasticsearch

    1.ELK介绍 1> Elasticsearch是实时全文搜索和分析引擎, 提供搜集.分析.存储数据三大功能: 是一套开放REST和JAVA API等结构提供高效搜索功能,可扩展的分布式系统. ...

  2. Springboot Application 集成 OSGI 框架开发

    内容来源:https://www.ibm.com/developerworks/cn/java/j-springboot-application-integrated-osgi-framework-d ...

  3. linux下elasticsearch集成mongodb详细教程

    由于公司业务需要,要用elasticsearch做索引库实现搜索功能,历尽千辛万苦,最后总算把mongodb和elasticsearch集成成功 1.搭建mongodb集群 参考https://www ...

  4. 【读书笔记】Elasticsearch集成Hadoop最佳实践

    前言 本文记录[Elasticsearch集成Hadoop最佳实战]读书笔记 本书总计209页,共7章节,计划时间:20180712-20180717 (每天至少40页) 本文代码地址: https: ...

  5. SpringBoot项目集成Hystrix

    Hystrix Hystrix是由Netflix开源的一个服务隔离组件,通过服务隔离来避免由于依赖延迟.异常,引起资源耗尽导致系统不可用的解决方案. 1.什么是服务熔断   服务熔断就是对该服务的调用 ...

  6. 钉钉通知机器人与SpringBoot的集成

    Spring Boot Admin 集成自定义监控告警(2.0.1版本)------钉钉机器人 - yuancao24的博客 - CSDN博客https://blog.csdn.net/yuancao ...

  7. SpringBoot项目集成PageHelper使用

    SpringBoot项目集成PageHelper使用 一.开始 ​ 地址:https://github.com/pagehelper/Mybatis-PageHelper ​ 在spring boot ...

  8. Springboot简单集成ActiveMQ

    Springboot简单集成ActiveMQ 消息发送者的实现 pom.xml添加依赖 <dependency> <groupId>org.springframework.bo ...

  9. 在springboot中集成mybatis开发

    在springboot中利用mybatis框架进行开发需要集成mybatis才能进行开发,那么如何在springboot中集成mybatis呢?按照以下几个步骤就可以实现springboot集成myb ...

随机推荐

  1. web开发性能优化---数据库篇

    1. 查询出的数据量过大(可以采用多次查询,其他的方法降低数据量),尽量采取分页查询数据 2.锁或者死锁(这也是查询慢最常见的问题,是程序设计的缺陷) 3.返回了不必要的行和列 用OR的字句可以分解成 ...

  2. 畅通工程 HDU - 1232

    某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府"畅通工程"的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接 ...

  3. java实现组合问题

    刚才刚更新了排列问题,顺带把组合问题也发表一下 1.问题描述: 已知有m个球,从m个球中取n个球有多少种不同的取法. 2.输入示例: 请输入总球的个数和要取的球的个数 6 5 3.输出示例: 共有6种 ...

  4. ListView 无 DataSource 依然用 DataPager 翻页

    ListView 有 DataSource 使用 DataPager 翻页ListView 无 DataSource 使用 DataPager 翻页问题描述点击两次才能翻页返回上一页,内容为空解决方法 ...

  5. java——基础语法

    java基础语法 1.关键字:java赋予特殊含义的单词. 2.标识符:程序中开发人员自定义的名词,例如:类名,函数名,变量名(注意事项:①不能以阿拉伯数字开头②不能采用关键字). 3.常量:固定的数 ...

  6. 【Luogu3444】ORK-Ploughing(贪心)

    [Luogu3444]ORK-Ploughing(贪心) 题面 Luogu 题解 我们知道,如果我们选定了以横向为主,或者纵向为主, 那么就有尽可能减少另一个方向上耕地的次数 所以分开贪心,但是本质相 ...

  7. C++学习-11

    虚函数表,调试下断点,指针的自动变量 含有虚函数的类,它的内部含有虚指针指向虚函数表,此时的空类占有4个字节,不管有多少个虚函数,只需要一个虚函数指针指向虚函数表就可以了 构造函数不可以是虚函数,如果 ...

  8. js备战春招の三

    DOM (Document Object Model)(文档对象模型)是用于访问 HTML 元素的正式 W3C 标准. window.alert() 弹出警告框. document.write() 方 ...

  9. IO模式和IO多路复用

    网络编程里常听到阻塞IO.非阻塞IO.同步IO.异步IO等概念,总听别人装13不如自己下来钻研一下.不过,搞清楚这些概念之前,还得先回顾一些基础的概念. 1 基础知识回顾 注意:咱们下面说的都是Lin ...

  10. git团队协作

    hi,team,我们目前使用的是git做项目管理,它是非常优秀的版本控制工具,使用好可以极大提高我们团队开发效率.但是,出现不必要的冲突和代码丢失就要费时解决这些可避免的问题. git开发流程 这个流 ...