作为互联网热点知识的ElasticSearch
,怎能不学。如果你有空余时间,欢迎入门;如果你没空余时间,也欢迎走马观花看一眼。走过如果不要错过,这是一篇自我感觉相对对入门者来说比较全面
的文章了,希望对大家有帮助,有什么疑问或者建议欢迎留言讨论。
Elasticsearch
是一个开源
的分布式
、高扩展
、高实时
的RESTful 搜索和分析引擎
,基于Lucene
。Elasticsearch
是与名为Logstash的数据收集和日志解析引擎以及名为Kibana的分析和可视化平台一起开发的。这三个产品被设计成一个集成解决方案,称为“Elastic Stack”(以前称为“ELK stack”)。Elasticsearch
能很方便的使大量数据具有搜索
、分析
和探索
的能力,能使数据在生产环境变得更有价值
。提交
到Elastic Search 数据库中,再通过分词
控制器去将对应的语句分词,将其权重和分词
结果一并存入数据,当用户搜索
数据时候,再根据权重将结果排名
,打分
,再将返回
结果呈现给用户。Wikipedia
使用 Elasticsearch 提供带有高亮片段的全文搜索,还有 search-as-you-type 和 did-you-mean 的建议。2. Stack Overflow
将地理位置查询融入全文检索中去,并且使用 more-like-this 接口去查找相关的问题和回答。3. GitHub
使用 Elasticsearch 对1300亿行代码进行查询。9200
是http
协议的RESTful
接口。9300
是tcp
通讯端口,集群
间和TCPClient
都走的它。DB | ES |
---|---|
`database`数据库 | `index`索引 |
`table`表 | `type`类型 |
`row`行(一条数据) | `document`文档 |
`column`列(字段名) | `field`字段 |
https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.8.1.zip
下载6.8.1版本 bin\elasticsearch.bat
http://127.0.0.1:9200/
,见到以下返回信息(目前推荐ES6.8.1的版本,比较靠谱,minimum_index_compatibility_version=5.X
的,最新版ES7最低的client版本是6.X,会有兼容问题,请看末尾版本兼容问题
部分){
"name": "sUR4zrr",
"cluster_name": "elasticsearch",
"cluster_uuid": "ODsZw-P1QMe9CDeOqEQQvA",
"version": {
"number": "6.7.1",
"build_flavor": "default",
"build_type": "zip",
"build_hash": "2f32220",
"build_date": "2019-04-02T15:59:27.961366Z",
"build_snapshot": false,
"lucene_version": "7.7.0",
"minimum_wire_compatibility_version": "5.6.0",
"minimum_index_compatibility_version": "5.0.0"
},
"tagline": "You Know, for Search"
}
elasticsearch-head
https://www.chromefor.com/elasticsearch-head_v0-1-4/ 和 dejavu-elasticsearch-web-ui
https://www.chromefor.com/dejavu-elasticsearch-web-ui_v3-4-0/篇幅较长,请看 https://blog.csdn.net/moshowgame/article/details/99413448
篇幅较长,请看 https://zhengkai.blog.csdn.net/article/details/99448661
这里补充几个常用
的API,以便大家对ES的REST API有简单的了解:
curl -X PUT \ http://localhost:9200/blog
,PUT请求,后面的blog是要新建的index,也就是这个api相当于新建一个数据库curl -X POST \ http://localhost:9200/blog/article \ -d ' { "author": "zhengkai.blog.csdn.net", "createtime": 1563689639575, "id": 2, "text": "Elasticsearch是一个开源的分布式、高扩展、高实时的RESTful 搜索和分析引擎,基于Lucene......", "title": "SpringBoot整合ElasticSearch" }'
,POST请求,如果不存在叫article的type类型/table表,则新增,并插入记录。curl -X GET \ 'http://localhost:9200/article_info/doc/61969/_termvectors?fields=title'
格式为/${index}/${type}/${id}/_termvectors?fields=${fields_name}
,GET请求,查询分词结果。返回的JSON中term_vectors.field.terms
里面就是分词结果。curl -X POST \http://localhost:9200/_search -d '{"query":{"bool":{"must":[{"wildcard":{"title.keyword":{"wildcard":"*SpringBoot*","boost":1}}}],"disable_coord":false,"adjust_pure_negative":true,"boost":1}}}'
,POST请求,进行搜索。2019.7.23 补充。这个查询情况比较复杂,补充一些**【ElasticSearch分词和查询相关】**东西:
{"query":{"wildcard": { "title": "*springboot*" }}}
可以查询到包含SpringBoot和springboot忽略大小写
的标题,走分词,所以只能用小写查。而{"query":{"wildcard": { "title": "*SpringBoot*" }}}
什么都查询不出来。。。{"query":{"wildcard": { "title.keyword": "*SpringBoot*" }}}
可以查询到包含SpringBoot的大小写必须一致
的标题,不走分词。而{"query":{"wildcard": { "title.keyword": "*springboot*" }}}
`什么都查询不出来。。。{"query":{"match": { "title": "bootelasticsearch" }}}
,可以查询出来,而且无论bootelasticsearch
中什么字母是大写或者小写,忽略大小写
。。。{"query":{"term": { "title": "bootelasticsearch" }}}
,可以查询出来,且必须小写字母才能查询出来,其他都不行。。。以上情况很奇怪对吧,为什么呢,请看下文分解。。
bool
(boolQuery)和must
(boolQuery.must)的关系,就像sql的where
和and
一样,作为条件连接的桥梁来使用,多个条件的话,就使用多个must。wildcard
模糊查询,跟SQL的LIKE
查询很类似,条件"*SpringBoot*"
表示包含SpringBoot的文本。wildcard
的情况下,查询字段是text类型的话(es5以后没有string类型呢,分text和keyword,string数据put到es5中,默认是text
。),直接title
查询是走分词
的,例如查询springboot,将会查询到Spring;用title.keyword
的话这样可以不走分词,进行精准匹配。standard analyzer
,大写字母全部转为了小写字母
,并存入了倒排索引以供搜索。”SpringBootElasticSearch
”会被分解成[bootelasticsearch]
写入倒排索引(使用3的分词结果接口可以看到。坑啊!不是应[该spring,boot,elasticsearch]吗!!!)。 所以term query
查询的是倒排索引
中确切的term,必须要匹配到大写的BootElasticSearch
;而match query
会对filed进行分词操作,然后在查询,忽略大小写
。一个 bool 过滤器由三部分组成:
{
"bool" : {
"must" : [],
"should" : [],
"must_not" : [],
}
}
下面是一个简单明了的SQL->Elasticsearch QL
:
SELECT product
FROM products
WHERE (price = 20 OR productID = "MOSHOW IN ACTION-#fJ3")
AND (price != 30)
用es写就是:
{
"query" : {
"filtered" : {
"filter" : {
"bool" : {
"should" : [
{ "term" : {"price" : 20}},
{ "term" : {"productID" : "MOSHOW IN ACTION-#fJ3"}}
],
"must_not" : {
"term" : {"price" : 30}
}
}
}
}
}
}
匹配查询 match 是个 核心 查询。无论需要查询什么字段, match 查询都应该会是首选的查询方式。 它是一个高级全文查询 ,这表示它既能处理全文字段,又能处理精确字段。
{
"query": {
"match": {
"title": "QUICK!"
}
}
}
执行上面这个 match 查询的步骤是:
相关度评分 _score
,这是种将 词频(term frequency
,即词 quick 在相关文档的 title 字段中出现的频率)和反向文档频率(inverse document frequency
,即词 quick 在所有文档的 title 字段中出现的频率),以及字段的长度(即字段越短相关度越高)
相结合的计算方式。与 prefix 前缀查询的特性类似, wildcard 通配符查询也是一种底层基于词的查询, 与前缀查询不同的是它允许指定匹配的正则式。它使用标准的 shell 通配符查询: ? 匹配任意字符, * 匹配 0 或多个字符
。
这个查询会匹配例如包含 W1F 7HW
和 W2F 8HW
的文档:
{
"query": {
"wildcard": {
"postcode": "W?F*HW"
}
}
}
这个查询会匹配邮政编码:
{
"query": {
"regexp": {
"postcode": "W[0-9].+"
}
}
}
term 查询对于查找单个值非常有用,但通常我们可能想搜索多个值。 如果我们想要查找价格字段值为 $20 或 $30 的文档该如何处理呢?
SELECT product
FROM products
WHERE (price = 20 OR price = 30)
不需要使用多个 term
查询,我们只要用单个 terms
查询(注意末尾的 s ), terms 查询好比是 term 查询的复数形式(以英语名词的单复数做比)。
它几乎与 term 的使用方式一模一样,与指定单个价格不同,我们只要将 term 字段的值改为数组即可。另外,与 term 查询一样,也需要将其置入 filter 语句的constant_score常量评分查询
中使用:
{
"query" : {
"constant_score" : {
"filter" : {
"terms" : {
"price" : [20, 30]
}
}
}
}
}
range 查询可同时提供包含(inclusive)和不包含(exclusive)这两种范围表达式,可供组合的选项如下:
gt: > 大于(greater than)
lt: < 小于(less than)
gte: >= 大于或等于(greater than or equal to)
lte: <= 小于或等于(less than or equal to)
SELECT document
FROM products
WHERE price BETWEEN 20 AND 40
{
"query" : {
"constant_score" : {
"filter" : {
"range" : {
"price" : {
"gte" : 20,
"lt" : 40
}
}
}
}
}
}
前面都是基础,下面才是开始Coding。
项目源码已经上传到github,有需要可以参考或者下载使用。
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-elasticsearchartifactId>
dependency>
dependencies>
这里是application.ym
l的配置
server:
port: 9999
servlet:
context-path: /es
tomcat:
remote-ip-header: x-forward-for
uri-encoding: UTF-8
max-threads: 10
background-processor-delay: 30
spring:
http:
encoding:
force: true
charset: UTF-8
application:
name: spring-cloud-study-security-elasticsearch
author: zhengkai.blog.csdn.net
data:
elasticsearch:
cluster-nodes: 127.0.0.1:9300
cluster-name: elasticsearch
import java.util.Date;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import lombok.Data;
@Data
@Document(indexName = "article_info", type = "doc")
public class Article {
@Id
private Integer id;
private String title;
private String text;
private Date createtime;
private String author;
}
ArticleRepository
接口继承ElasticsearchRepository
来完成基本的CRUD
及分页
操作的,功能强大并且和普通JPA没有什么区别。保存的话直接用save就可以了,以下是search相关的方法:
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;
/**
* ElasticsearchRepository --> ElasticsearchCrudRepository --> PagingAndSortingRepository --> CrudRepository
* @author zhengkai.blog.csdn.net
*/
@Repository
public interface ArticleRepository extends ElasticsearchRepository<Article, Integer> {
}
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.softdev.system.demo.entity.Article;
import com.softdev.system.demo.repository.ArticleRepository;
import com.softdev.system.demo.util.ApiReturnUtil;
import cn.hutool.core.util.RandomUtil;
/**
* ElasticSearch控制器
* @author zhengkai.blog.csdn.net
* */
@RestController
public class ArticleController {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Autowired
private ArticleRepository articleRepository;
@GetMapping("new")
public Object newArticle(@RequestParam(defaultValue = "SpringBootElasticSearch") String title, @RequestParam(defaultValue = "`Elasticsearch` 是一个`开源`的`分布式`、`高扩展`、`高实时`的RESTful `搜索和分析引擎`,基于`Lucene`......") String text){
//构建并保存Article
Article article = new Article();
article.setId(RandomUtil.randomInt(10000,99999));
article.setTitle(title);
article.setText(text);
article.setCreatetime(new Date());
article.setAuthor("zhengkai.blog.csdn.net");
return ApiReturnUtil.success(article);
}
@GetMapping("save")
public Object save(@RequestParam(defaultValue = "SpringBootElasticSearch") String title, @RequestParam(defaultValue = "`Elasticsearch` 是一个`开源`的`分布式`、`高扩展`、`高实时`的RESTful `搜索和分析引擎`,基于`Lucene`......") String text){
//构建并保存Article
Article article = new Article();
article.setId(RandomUtil.randomInt(10000,99999));
article.setTitle(title);
article.setText(text);
article.setCreatetime(new Date());
article.setAuthor("zhengkai.blog.csdn.net");
articleRepository.save(article);
return ApiReturnUtil.success(article);
}
/**
* ElasticSearch之Search封装查询
* @author zhengkai.blog.csdn.net
* @param title 搜索标题
* @param pageable page = 第几页参数(第一页是0), value = 每页显示条数
*/
@GetMapping("search")
public Object search(@RequestParam(defaultValue = "SpringBoot") String title, @PageableDefault(page = 0, value = 10) Pageable pageable){
//以下查询等同于封装了{"query":{"bool":{"must":[{"wildcard":{"title.keyword":{"wildcard":"*SpringBoot*","boost":1}}}],"disable_coord":false,"adjust_pure_negative":true,"boost":1}}}
//按标题进行模糊查询
QueryBuilder queryBuilder = QueryBuilders.wildcardQuery("title.keyword", "*SpringBoot*");
//按照顺序构建builder,bool->must->wildcard ,有了上文的JSON,顺序就很好理解了
BoolQueryBuilder must = QueryBuilders.boolQuery().must(queryBuilder);
//封装pageable分页
Page<Article> queryResult = articleRepository.search(must,pageable);
//返回
return ApiReturnUtil.success(queryResult.getContent());
}
/**
* ElasticSearch之elasticsearchTemplate查询
* @author zhengkai.blog.csdn.net
* @param title 搜索标题
*/
@GetMapping("originSearch")
public Object originSearch(@RequestParam(defaultValue = "SpringBoot") String title) {
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
QueryBuilder queryBuilder = QueryBuilders.wildcardQuery("title.keyword", "*SpringBoot*");
BoolQueryBuilder must = boolQuery.must(queryBuilder);
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
NativeSearchQuery build = nativeSearchQueryBuilder.withQuery(must).build();
List<Article> queryForList = elasticsearchTemplate.queryForList(build, Article.class);
return ApiReturnUtil.success(queryForList);
}
}
http://localhost:9999/es/save
进行保存(如果你想用API保存,可以http://localhost:9999/es/new
访问,得到一些JSON数据)http://localhost:9999/es/save?title=ElasticSearch
保存一条title不包含SpringBoot的数据(下文根据SpringBoot
来检索)ElasticSearch Head
和Dejavu UI
插件进行查看(前提是安装好插件!!!否则请跳过。。。)Structured Query
界面中选择 must+doc.title.keyword+wildcard+*SpringBoot*
的查询条件,成功查询到数据。http://localhost:9999/es/search
或者用ES的RESTful API ,POST
以下链接:
http://localhost:9200/_search
{“query”:{“bool”:{“must”:[{“wildcard”:{“title.keyword”:{“wildcard”:“SpringBoot”,“boost”:1}}}],“disable_coord”:false,“adjust_pure_negative”:true,“boost”:1}}}
es返回结果json解析:
took
:整个搜索请求花费了多少毫秒hits.total
:本次搜索,返回了几条结果hits.max_score
:本次搜索的所有结果中,最大的相关度分数是多少,每一条document对于search的相关度,越相关,_score分数越大,排位越靠前hits.hits
:默认查询前10条数据,完整数据,_score降序排序shards
:shards fail的条件(primary和replica全部挂掉),不影响其他shard。默认情况下来说,一个搜索请求,会打到一个index的所有primary shard上去,当然了,每个primary shard都可能会有一个或多个replic shard,所以请求也可以到primary shard的其中一个replica shard上去。timeout
:默认无timeout,latency平衡completeness,手动指定timeout,timeout查询执行机制,格式:timeout=10ms,timeout=1s,timeout=1mGET /_search?timeout=10m这个报错转换过来就是:远程主机强迫关闭了一个现有的连接
exception caught on transport layer [Netty4TcpChannel{localAddress=/127.0.0.1:9300, remoteAddress=/127.0.0.1:53494}], closing connection
java.io.IOException: 杩滅▼涓绘満寮鸿揩鍏抽棴浜嗕竴涓幇鏈夌殑杩炴帴銆?
at sun.nio.ch.SocketDispatcher.read0(Native Method) ~[?:?]
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43) ~[?:?]
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:276) ~[?:?]
at sun.nio.ch.IOUtil.read(IOUtil.java:245) ~[?:?]
at sun.nio.ch.IOUtil.read(IOUtil.java:223) ~[?:?]
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:358) ~[?:?]
at io.netty.buffer.PooledHeapByteBuf.setBytes(PooledHeapByteBuf.java:261) ~[netty-buffer-4.1.32.Final.jar:4.1.32.Final]
at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1132) ~[netty-buffer-4.1.32.Final.jar:4.1.32.Final]
at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:347) ~[netty-transport-4.1.32.Final.jar:4.1.32.Final]
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:148) [netty-transport-4.1.32.Final.jar:4.1.32.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:656) [netty-transport-4.1.32.Final.jar:4.1.32.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysPlain(NioEventLoop.java:556) [netty-transport-4.1.32.Final.jar:4.1.32.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:510) [netty-transport-4.1.32.Final.jar:4.1.32.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:470) [netty-transport-4.1.32.Final.jar:4.1.32.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:909) [netty-common-4.1.32.Final.jar:4.1.32.Final]
at java.lang.Thread.run(Thread.java:834) [?:?]
minimum_index_compatibility_version
这里定义的最低版本会受spring-boot-starter-data-elasticsearch
的版本影响。
所以目前推荐ES6,6.8.1左右的版本,比较靠谱。我一开始就是到官网下载最新版本,就被坑了。
如果你看到JAVA控制台有以下错误,基本就是版本兼容性问题了,直接访问localhost:9200
获取版本信息。
org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available
推断错误的话。可以从一下日志查找思路,特别是看ES控制台输出的内容,可以清楚的看到
closing connection
java.lang.IllegalStateException: Received handshake message from unsupported version: [5.0.0] minimal compatible version is: [6.8.0]
{
"name" : "WORKPC-MOSHOW",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "fDlrxuUcTjqgvfpWbl3Hcg",
"version" : {
"number" : "7.2.0",
"build_flavor" : "default",
"build_type" : "zip",
"build_hash" : "508c38a",
"build_date" : "2019-06-20T15:54:18.811730Z",
"build_snapshot" : false,
"lucene_version" : "8.0.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
[/es] threw exception [Request processing failed; nested exception is NoNodeAvailableException[None of the configured nodes are available: [{#transport#-1}{mQ1hg9-tT3mvRnfLIAaZHg}{127.0.0.1}{127.0.0.1:9300}]]] with root cause
org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available: [{#transport#-1}{mQ1hg9-tT3mvRnfLIAaZHg}{127.0.0.1}{127.0.0.1:9300}]
at org.elasticsearch.client.transport.TransportClientNodesService.ensureNodesAreAvailable(TransportClientNodesService.java:347) ~[elasticsearch-5.6.11.jar:5.6.11]
at org.elasticsearch.client.transport.TransportClientNodesService.execute(TransportClientNodesService.java:245) ~[elasticsearch-5.6.11.jar:5.6.11]
at org.elasticsearch.client.transport.TransportProxyClient.execute(TransportProxyClient.java:59) ~[elasticsearch-5.6.11.jar:5.6.11]
at org.elasticsearch.client.transport.TransportClient.doExecute(TransportClient.java:366) ~[elasticsearch-5.6.11.jar:5.6.11]
at org.elasticsearch.client.support.AbstractClient.execute(AbstractClient.java:408) ~[elasticsearch-5.6.11.jar:5.6.11]
at org.elasticsearch.action.ActionRequestBuilder.execute(ActionRequestBuilder.java:80) ~[elasticsearch-5.6.11.jar:5.6.11]
at org.elasticsearch.action.ActionRequestBuilder.execute(ActionRequestBuilder.java:54) ~[elasticsearch-5.6.11.jar:5.6.11]
at org.springframework.data.elasticsearch.core.ElasticsearchTemplate.index(ElasticsearchTemplate.java:571) ~[spring-data-elasticsearch-3.0.10.RELEASE.jar:3.0.10.RELEASE]
at org.springframework.data.elasticsearch.repository.support.AbstractElasticsearchRepository.save(AbstractElasticsearchRepository.java:156) ~[spring-data-elasticsearch-3.0.10.RELEASE.jar:3.0.10.RELEASE]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.__invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45009) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45012) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:377) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:200) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:641) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:605) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:590) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at com.sun.proxy.$Proxy88.save(Unknown Source) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.__invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45009) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45012) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
at org.zeroturnaround.javarebel.integration.util.ReloadingProxyFactory$ReloadingMethodHandler.invoke(SourceFile:74) ~[na:201907051008]
at com.sun.proxy.$Proxy88.save(Unknown Source) ~[na:na]
at com.softdev.system.demo.controller.ArticleController.save(ArticleController.java:38) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.__invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45009) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45012) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:891) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.34.jar:8.5.34]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
at org.apache.catalina.core.StandardContextValve.__invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.34.jar:8.5.34]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:41002) [tomcat-embed-core-8.5.34.jar:8.5.34]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493) [tomcat-embed-core-8.5.34.jar:8.5.34]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.34.jar:8.5.34]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.34.jar:8.5.34]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.34.jar:8.5.34]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.34.jar:8.5.34]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:800) [tomcat-embed-core-8.5.34.jar:8.5.34]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.34.jar:8.5.34]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:806) [tomcat-embed-core-8.5.34.jar:8.5.34]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498) [tomcat-embed-core-8.5.34.jar:8.5.34]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.34.jar:8.5.34]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135) [na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [na:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.34.jar:8.5.34]
at java.base/java.lang.Thread.run(Thread.java:844) [na:na]
[WARN ][o.e.t.TcpTransport ] [WORKPC-MOSHOW] exception caught on transport layer [Netty4TcpChannel{localAddress=/127.0.0.1:9300, remoteAddress=/127.0.0.1:64883}], closing connection
java.lang.IllegalStateException: Received handshake message from unsupported version: [5.0.0] minimal compatible version is: [6.8.0]
at org.elasticsearch.transport.InboundMessage.ensureVersionCompatibility(InboundMessage.java:137) ~[elasticsearch-7.2.0.jar:7.2.0]
at org.elasticsearch.transport.InboundMessage.access$000(InboundMessage.java:39) ~[elasticsearch-7.2.0.jar:7.2.0]
at org.elasticsearch.transport.InboundMessage$Reader.deserialize(InboundMessage.java:76) ~[elasticsearch-7.2.0.jar:7.2.0]
at org.elasticsearch.transport.InboundHandler.messageReceived(InboundHandler.java:116) ~[elasticsearch-7.2.0.jar:7.2.0]
at org.elasticsearch.transport.InboundHandler.inboundMessage(InboundHandler.java:105) ~[elasticsearch-7.2.0.jar:7.2.0]
at org.elasticsearch.transport.TcpTransport.inboundMessage(TcpTransport.java:660) [elasticsearch-7.2.0.jar:7.2.0]
at org.elasticsearch.transport.netty4.Netty4MessageChannelHandler.channelRead(Netty4MessageChannelHandler.java:62) [transport-netty4-client-7.2.0.jar:7.2.0]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:323) [netty-codec-4.1.35.Final.jar:4.1.35.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:297) [netty-codec-4.1.35.Final.jar:4.1.35.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
at io.netty.handler.logging.LoggingHandler.channelRead(LoggingHandler.java:241) [netty-handler-4.1.35.Final.jar:4.1.35.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1408) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:930) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:682) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysPlain(NioEventLoop.java:582) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:536) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:906) [netty-common-4.1.35.Final.jar:4.1.35.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) [netty-common-4.1.35.Final.jar:4.1.35.Final]
at java.lang.Thread.run(Thread.java:834) [?:?]
2019.8.13补充。es返回结果json解析。
2019.8.12补充。bool query/range query/match query/term query/wildcard®ex query等几个关键查询,更多详情请看官方文档 全文搜索|中文 和 Query DSL|英文 。
2019.7.23 补充。这个查询情况比较复杂,补充一些**【ElasticSearch分词和查询相关】**东西。