Elasticsearch 是一个分布式、RESTful 风格的搜索和数据分析引擎,能够解决不断涌现出的各种用例。 作为 Elastic Stack 的核心,它集中存储您的数据,帮助您发现意料之中以及意料之外的情况。
官方文档
官方中文
社区中文1
社区中文2
1、Index (索引)
2、Type(类型)
3、Document(文档)
4、倒排索引机制
将整句拆分单词、相关性得分等
安装 elasticsearch
# 指定安装 elasticsearch:7.17.1
$ docker pull elasticsearch:7.17.1
# 或者默认安装 elasticsearch 最新版本
$ docker pull elasticsearch
# 安装 kibana:7.17.1
# kibana 是可视化工具,作用类似于 Mysql的查看工具
$ docker pull kibana:7.17.1
# 查看docker已安装的容器列表
$ docker images
# 查看可用内存大小,-m 以单位M展示
$ free -m
# 创建实例完整命令,注意,如果执行没有权限,请 sudo su ,切到root账户权限, 或者所有命令前加 sudo
$ mkdir -p /mydata/elasticsearch/config # mkdir 创建指定目录层级
$ mkdir -p /mydata/elasticsearch/data # mkdir 创建指定目录层级
$ echo "http.host: 0.0.0.0" >> /mydata/elasticsearch/config/elasticsearch.yml # 写入内容到指定xx.yml配置文件
$ docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms64m -Xmx512m" \
-v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
-v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.17.1
# docker参数详解
--name elasticsearch # 为docker容器创建 名为“elasticsearch”的容器
-p 9200:9200 # 将 容器内的 9200 端口 映射为 容器外的 9200 端口(9200 是 REST-API的服务端口)
-p 9300:9300 # 将 容器内的 9300 端口 映射为 容器外的 9300 端口(9300 是 Es集群之间的通信端口)
-e "discovery.type=single-node" # -e 设置。 设置 “单节点运行模式”
-e ES_JAVA_OPTS="-Xms64m -Xmx512m" # -e 设置。 设置 “JAVA虚拟器占用的内存大小,-Xms64m:初始64M;-Xmx512m:最大占用512M”,如果不设置就启动,默认会占用整个服务器内存,如果是本地搭建的虚拟机,容易卡死,建议根据实际情况设置大小。
-v #-v 设置挂载路径
-v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml # 将容器外部的 /mydata/elasticsearch/config/elasticsearch.yml 文件挂载为 容器内部的 /usr/share/elasticsearch/config/elasticsearch.yml 文件,以后修改容器外部的elasticsearch.yml配置文件相当于修改了容器内部的 elasticsearch.yml 文件。
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data # 同上,挂载data数据目录
-v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins # 同上,挂载plugins插件目录
-d elasticsearch:7.17.1# -d 是docker容器后台启动命令。这里指定后台启动,使用”elasticsearch:7.17.1“这个镜像
# 查看运行中的容器,是否有 elasticsearch
$ docker ps
# 浏览器访问 http://ip:9200(ip为服务器地址),能访问成功,就是正常。
# 如果访问失败,可能是 安装目录权限不足 或者 配置文件有问题
正常访问 es,会返回 es的 版本JSON信息,如下图:
Kibana 是一个开源分析和可视化平台,旨在与 Elasticsearch 一起使用。您可以使用 Kibana 搜索、查看存储在 Elasticsearch 索引中的数据并与之交互。您可以轻松地执行高级数据分析并在各种图表、表格和地图中可视化您的数据。
# docker 容器 安裝 kibana 命令,注意 kibana 的版本必须 与 ES 的版本保持一直,这里是安装 7.17.1版本
$ docker run --name kibana -e ELASTICSEARCH_HOSTS=http://192.168.56.10:9200 -p 5601:5601 \
-d kibana:7.17.1
# docker参数详解
--name kibana # 为docker容器创建 名为“kibana”的容器
-p 5601:5601 # 将 容器内的 5601 端口 映射为 容器外的 5601 端口(5601 是 kibana的可视化访问默认端口 )
-v /mydata/kibana/config/kibana.yml:/usr/share/kibana/config/kibana.yml # 挂载配置文件
-e ELASTICSEARCH_HOSTS=http://192.168.56.10:9200 # -e 设置。 设置 “ELASTICSEARCH_URL”,设置安装es服务器的ip地址。注意:这里的ip是我本地服务器的ip地址,应该改为你自己的服务器ip地址
-d kibana:7.17.1 # -d 是docker容器后台启动命令。这里指定后台启动,使用”kibana:7.17.1“这个镜像
# 查看运行中的容器,是否有 kibana
$ docker ps
# 进入某容器内部,以kibana为例:
$ docker exec -it kibana /bin/bash # kibana配置文件路径为: /usr/share/kibana/config/kibana.yml
# 浏览器访问 http://ip:5601/ ip为服务器地址),能访问成功,就是正常。
# 如果访问失败,可能是 elsasticesarch 服务没找到,需要修改 kibana.yml 配置文件的host路径,重启kibana。
Kibana 官方使用说明文档(各种版本)
Kibana 运行在Docker容器的说明文档
# 设置Docker容器启动,自动启动
$ sudo docker update elasticsearch --restart=always
$ sudo docker update kibana --restart=always
Dev Tools
1、安装时可能会遇到,某个执行目录没有“执行”权限,导致服务启动失败的问题
# 查看 docker 容器 xx 服务的运行日志
$ docker logs xxx
# 查看 docker 容器中,elasticsearch服务的启动日志
$ docker logs elasticsearch
$ docker logs [CONTAINER ID]
# 赋予 最大权限 777 读写执行
$ chmod -R 777 /mydata/elasticsearch/
# docker容器启动 指定 [CONTAINER ID] 的服务
$ docker start elasticsearch
$ docker start [CONTAINER ID]
2、测试环境下,安装时没有设置 ES 的JVM初始内存和最大内存,导致默认 ES 启动占用内存过大,导致启动不了ES。
解决办法:安装时,设置参数”-e ES_JAVA_OPTS="-Xms64m -Xmx128m"
”,详解看上面的参数详解。
3、 Kibana 启动后,docker logs 日志提示 “Unable to retrieve version information from Elasticsearch nodes. getaddrinfo ENOTFOUND elasticsearch
”
解决办法:卸载安装的kibana ,修改”ELASTICSEARCH_HOSTS=http://192.168.56.10:9200
“ ip地址为es的服务器地址,重新安装kibana容器,启动后成功访问。
4、 第一次启动 elasticsearch 8.2.0 初始化时,提示“UnknownHostException: geoip.elastic.co
”
原因是:geoip.elastic.co 地址无法访问,暂时无法解决,等过段时间试试。或者变更 elasticsearch 版本。
pe": "server", "timestamp": "2022-05-31T17:52:24,462Z", "level": "ERROR", "component": "o.e.i.g.GeoIpDownloader", "cluster.name": "elasticsearch", "node.name": "def72f49dcae", "message": "exception during geoip databases update", "cluster.uuid": "4k9KkOwMTP-Qf7HG5F2_Og", "node.id": "6w1mM9DSQsaW3G6otMQivA" ,
"stacktrace": ["java.net.UnknownHostException: geoip.elastic.co",
"at sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:564) ~[?:?]",
"at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327) ~[?:?]",
"at java.net.Socket.connect(Socket.java:633) ~[?:?]",
"at sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:299) ~[?:?]",
"at sun.net.NetworkClient.doConnect(NetworkClient.java:178) ~[?:?]",
"at sun.net.www.http.HttpClient.openServer(HttpClient.java:498) ~[?:?]",
"at sun.net.www.http.HttpClient.openServer(HttpClient.java:603) ~[?:?]",
"at sun.net.www.protocol.https.HttpsClient.(HttpsClient.java:264) ~[?:?]" ,
"at sun.net.www.protocol.https.HttpsClient.New(HttpsClient.java:378) ~[?:?]",
"at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.getNewHttpClient(AbstractD
5、安装 ik分词插件后,elasticsearch 重启提示“org.elasticsearch.action.search.SearchPhaseExecutionException: all shards failed
”
{"type": "server", "timestamp": "2022-06-01T06:50:20,171Z", "level": "WARN", "component": "r.suppressed", "cluster.name": "elasticsearch", "node.name": "c2a7f608e410", "message": "path: /.kibana_task_manager/_search, params: {ignore_unavailable=true, index=.kibana_task_manager, track_total_hits=true}", "cluster.uuid": "_bgipz4aT6iwCbr86r6DBA", "node.id": "IC_VxrpJRWaffQngBN2HdQ" ,
"stacktrace": ["org.elasticsearch.action.search.SearchPhaseExecutionException: all shards failed",
"at org.elasticsearch.action.search.AbstractSearchAsyncAction.onPhaseFailure(AbstractSearchAsyncAction.java:713) [elasticsearch-7.17.1.jar:7.17.1]",
"at org.elasticsearch.action.search.AbstractSearchAsyncAction.executeNextPhase(AbstractSearchAsyncAction.java:400) [elasticsearch-7.17.1.jar:7.17.1]",
"at org.elasticsearch.action.search.AbstractSearchAsyncAction.onPhaseDone(AbstractSearchAsyncAction.java:745) [elasticsearch-7.17.1.jar:7.17.1]",
"at org.elasticsearch.action.search.AbstractSearchAsyncAction.onShardFailure(AbstractSearchAsyncAction.java:497) [elasticsearch-7.17.1.jar:7.17.1]",
"at org.elasticsearch.action.search.AbstractSearchAsyncAction.performPhaseOnShard(AbstractSearchAsyncAction.java:308) [elasticsearch-7.17.1.jar:7.17.1]",
"at org.elasticsearch.action.search.AbstractSearchAsyncAction.run(AbstractSearchAsyncAction.java:244) [elasticsearch-7.17.1.jar:7.17.1]",
"at org.elasticsearch.action.search.AbstractSearchAsyncAction.executePhase(AbstractSearchAsyncAction.java:454) [elasticsearch-7.17.1.jar:7.17.1]",
"at org.elasticsearch.action.search.AbstractSearchAsyncAction.start(AbstractSearchAsyncAction.java:199) [elasticsearch-7.17.1.jar:7.17.1]",
"at org.elasticsearch.action.search.TransportSearchAction.executeSearch(TransportSearchAction.java:1048) [elasticsearch-7.17.1.jar:7.17.1]",
"at org.elasticsearch.action.search.TransportSearchAction.executeLocalSearch(TransportSearchAction.java:763) [ela
# 查看所有节点
GET /_cat/nodes
# 查看 es 健康状态
GET /_cat/health
# 查看主节点
GET /_cat/master
# 查看所有索引 类似于 mysql 的 show databases;
GET /_cat/indices
保存一个数据,保存在哪个索引的哪个类型下,指定用哪个唯一标识
PUT/POST customer/external/I;在customer索引下的external类型下保存1号数据
(
PUT
和POST
都可以)
POST
新增。如果不指定id,会自动生成id。指定id就会修改这个数据,并新增版本号
PUT
新增 OR 修改。可以新增也可以修改。
PUT
必须指定id;由于PUT需要指定id,我们一般都用来做修改操作,不指定id会报错。
// PUT customer/external/1
{
"name" : "John Doe"
}
GET customer/external/1
(更新携带
?if_seq_no=0&if_primary_term=1
)GET customer/external/1?if_seq_no=0&if_primary_term=1
结果:
{
"index":"customer",//在哪个索引
"_type":"external", //在哪个类型
"id":"1" //记录id
"_version":2, //版本号
"seq_no":1, //并发控制字段,每次更新就会+1,用来做乐观锁
"primary_term":1, //同上,主分片重新分配,如重启,就会变化
"found":true,
"source":{
"name":"John Doe"
}
}
GET /xx/_mapping
// POST customer/external/1/_update
{
"doc": {
"name": "John Doew"
}
}
//或者 POST customer/external/1
{
"name":"John Doe2"
}
//或者 PUT customer/external/1
【不同】:
POST
操作会对比源文档数据,如果相同不会有什么操作,文档 version 不增加
PUT
操作总会将数据重新保存并增加 version 版本:带
_update
对比元数据,如果一样就不进行任何操作。看场景:
对于大并发更新,不带update;
对于大并发查询偶尔更新,带update,对比更新,重新计算分配规侧。
● 更新同时增加属性 POST customer/external/1/_update
{
"doc": {
"name": "John Doew",
"age": 20
}
}
DELETE customer/external/1
DELETE customer
POST customer/external/bulk
{"index":{"_id":"1"}
{"name":"John Doe"}
{"index":{"_id":"2"}
{"name":"Jane Doe"}
【语法格式】:
{action:{metadata} \n
{request body} \n
{action:{metadata}} \n
{request body} \n
【复杂实例】:
POST/_bulk
{"delete":{"_index":"website""type":"blog","_id":"123"}}
{"create":{"_index":"website","type":"blog","_id":"123"}}
{"title":{"My first blog post"}
{"index":{"_index":"website","type":"blog"}}
{"title":"My second blog post"}
{"update":{"_index":"website","type":"blog","id":"123","retry_on_conflict":3}}{"doc":{"title":"My updated blog post"}}
# bulk AP1以此按顺序执行所有的action(动作)。如果一个单个的动作因任何原因而失败,它将继续处理它后面剩余的动作。当 bulk AP I返回时,它将提供每个动作的状态(与发送的顺序相同),所以您可以检查是否一个指定的动作是不是失败了。
测试数据存入:
POST bank/account/_bulk
ES支持两种基本方式检索:
- 一个是通过使用 REST request URI发送搜索参数(uri + 检索参数)
- 另一个是通过使用 REST request body来发送它们(uri + 请求体)
响应结果解释:
took-Elasticsearch 执行搜索的时间(毫秒)
time_out - 告诉我们搜索是否超时
_shards -告诉我们多少个分片被搜索了,以及统计了成功/失败的搜索分片
hits -搜索结果
hits.total -搜索结果
hits.hits -实际的搜索结果数组(默认为前10的文档)
sort -结果的排序key(键)(没有则按score排序)
score和max_score -相关性得分和最高得分(全文检索用)
GET bank/_search
{
"query":{
"match_all":{}
},
"sort":[
{
"account_number":{
"order":"desc"
}
}
]
}
HTTP客户端工具(POSTMAN),get请求不能携带请求体,我们变为post也是一样的
我们 POST 一个 JSON 风格的查询请求体到 _search API。
需要了解,一旦搜索的结果被返回,Elasticsearch就完成了这次请求,并且不会维护任何服务器的资源或者结果的 cursor (游标)
Elasticsearch 提供了一个可以执行查询的 Json风格的 DSL(domain-specific language 领域特定语言)。这个被称为Query DSL。该查询语言非常全面,并且刚开始的时候感觉有点复杂,真正学好它的方法是从一些基础的示例开始的。
一个查询语句的典型结构
GET bank/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"balance": {
"order": "desc"
}
}
],
"from": 0,
"size": 2,
"_source": [
"age",
"balance"
]
}
// match_all 查询所有
// sort : 排序,指定根据 某个字段 aes 或者 desc 排序
// from 和 size : 指定分页查询,从 0开始查询,每页size=2
// _source : 指定只展示哪个字段,相当于 MySQL 的 select
_source
match
,模糊匹配GET bank/_search
{
"query": {
"match": {
"address": "Mill"
}
}
}
// Match 匹配某个字段,如果该字段type是 text,会自动分词模糊匹配,_source 是分数,越高分匹配度越高
match _phrase
短语匹配GET bank/_search
{
"query": {
"match_phrase": {
"address": "Mill Road"
}
}
}
GET bank/_search
{
"query": {
"match": {
"address.keyword": "Mill Road"
}
}
}
// match_phrase 与 xx.keyword 效果不一样。前者是“分词短语匹配”,后者是“精确匹配”
multi_match
多字段匹配GET bank/_search
{
"query": {
"multi_match": {
"query": "mill movico",
"fields": ["address","city"]
}
}
}
// fields :指定字段,这里指定的两个字段,只要有个其中一直模糊匹配到 query 的分词,都会被查到,_source 是相关性得分,越大值匹配度越高。
bool
复合查询bool 用来做复合查询:
复合语句可以合并任何其它查询语句,包括复合语句,了解这一点是很重要的。这就意味着,复合语句之间可以互相嵌套,可以表达非常复杂的逻辑。
must
: 必须达到 must 列举的所有条件才匹配must_not
: 必须不匹配的才会被查到should
: 可以匹配,也可以不匹配GET bank/_search
{
"query": {
"bool": {
"must": [
{"match": {
"gender": "M"
}},
{
"match": {
"address": "mill"
}
}
],
"must_not": [
{"match": {
"age": "28"
}}
],
"should": [
{"match": {
"lastname": "wallace"
}}
]
}
}
}
filter
结果过滤并不是所有的查询都需要产生分数,特别是那些仅用于"filtering”(过滤)的文档。为了不中计算分数Elasticsearch会自动检查场景并且优化查询的执行。这种场景,适合使用
filter
关键字过滤
GET bank/_search
{
"query": {
"bool": {
"must": [
{ "range": {
"age": {
"gte": 10,
"lte": 20
}
}}
]
}
}
}
GET bank/_search
{
"query": {
"bool": {
"filter": [
{
"range": {
"age": {
"gte": 10,
"lte": 20
}
}
}
]
}
}
}
// filter : 查到的"max_score" =0.0
// must-range: 查到的数据 "max_score" = 1.0
term
非text字段匹配和
match
一样。匹配某个属性的值。全文检索字段用match
,其他非text
字段匹配用term
。比如type
类似是Long
、Integer
数字类型的字段,必须用term
匹配,否则会导致 es查询报错。
aggregations
聚合查询聚合提供了从数据中分组和提取数据的能力。最简单的聚合方法大致等于
SQL GROUP BY
和SQL聚合函数
。在Elasticsearch中,您有执行搜索返回hits
(命中结果),并且同时返回聚合结果,把一个响应中的所有hits
(命中结果)分隔开的能力。这是非常强大且有效的,您可以执行查询和多个聚合,并且在一次使用中得到各自的(任何一个的)返回结果,使用一次简洁和简化的API来避免网络往返。
// aggs 聚合格式
GET bank/_search
{
"query": {
"match_all": {}
},
"aggs": {
"NAME": {
"AGG_TYPE": {}
}
}
}
//搜索 address 中包含 mill 的所有人的年龄分布以及平均年龄,但不显示这些人的详情。
GET bank/_search
{
"query": {
"match": {
"address": "mill"
}
},
"aggs": {
"@ageAgg": {
"terms": {
"field": "age",
"size": 10
}
},
"@ageAvg":{
"avg": {
"field": "age"
}
}
}
}
//"aggs": 聚合关键字缩写
//"@ageAgg" 和“@ageAvg" 是自定义的别名,随便起
//"terms":非text类型字段匹配
//"avg":求平均值的聚合关键字
# 按照年龄聚合,并且这些年龄段中M的平均薪资和F的平均薪资;以及这个年龄段的总体平均薪资
GET bank/_search
{
"query": {
"match_all": {}
},
"aggs": {
"@ageagg": {
"terms": {
"field": "age",
"size": 100
},
"aggs": {
"@genderAgg": {
"terms": {
"field": "gender.keyword",
"size": 10
},
"aggs": {
"@balanceAvg": {
"avg": {
"field": "balance"
}
}
}
}
}
}
}
}
type
略 ,详情见官方
_mapping
,详情见官方示例:
// 获取 bank 的字段映射
GET /bank/_mapping
//查询结果如下:
#! Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security.
{
"bank" : {
"mappings" : {
"properties" : {
"account_number" : {
"type" : "long"
},
"address" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"age" : {
"type" : "long"
},
"balance" : {
"type" : "long"
},
"city" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"email" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"employer" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"firstname" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"gender" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"lastname" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"state" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
Es7及以上移除了type的概念。
关系型数据库中两个数据表示是独立的,即使他们里面有相同名称的列也不影响使用,但ES中不是这样的。elasticsearch是基于Lucene开发的搜索引擎,而ES中不同type下名称相同的fled最终在Lucene中的处理方式是一样的。
两个不同type下的两个user_name,在ES同一个索引下其实被认为是同一个filed,你必须在两个不同的type中定义相同的fled映射。否则,不同type中的相同字段名称就会在处理中出现冲突的情况,导致Lucene处理效率下降。
去掉type就是为了提高S处理数据的效率。
Elasticsearch 7.x
- URL中的type参数为可选。比如,索引一个文档不再要求提供文档类型。
Elasticsearch 8.x
- 不再支持URL中的type参数。
【解决】:
1)、将索引从多类型迁移到单类型,每种类型文档一个独立索引
2)、将已存在的索引下的类型数据,全部迁移到指定位置即可。详见数据迁移
PUT /my_index/
{
"mappings": {
"properties": {
"age": {
"type": "integer"
},
"email": {
"type": "keyword"
},
"name": {
"type": "text"
}
}
}
}
//执行结果
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "my_index"
}
// 这里假设 “/my_index”索引已经存在,还可以执行如下语句
// 语法 : PUT /my_index/_mapping
{
"properties":{
"字段名":{
"type":"keyword",
"index": false
}
}
}
// "type":"keyword" 作用是:指定当前字段类型是“关键字”类型
// "index": false 作用是:指定当前不作为全文索引字段,默认index 为true
PUT /my_index/_mapping
{
"properties":{
"balance":{
"type":"long"
}
}
}
//执行结果,而更新已经存在的 “age”映射字段,会报错
{
"acknowledged" : true
}
注意:对于已经存在的映射字段,es是不能直接更新的。更新会报错提示,因为已存在的映射,可能已经正在使用,如果es允许自己更新已存在的映射字段,映射关系可能会错乱导致其他错误。
如果一定要更新,只能通过创建新的索引,进行数据迁移,将旧映射的数据迁移到星的行的映射。
先创建出 new_xxx 的正确映射。
# 新建索引
PUT /new_bank
{
"mappings": {
"properties": {
"account_number": {
"type": "long"
},
"address": {
"type": "keyword"
},
"age": {
"type": "integer"
},
"balance": {
"type": "long"
},
"city": {
"type": "keyword"
},
"email": {
"type": "keyword"
},
"employer": {
"type": "keyword"
},
"firstname": {
"type": "text"
},
"gender": {
"type": "keyword"
},
"lastname": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"state": {
"type": "keyword"
}
}
}
}
然后使用如下方式进行数据迁移:
// 查询新旧索引映射字段规则
GET /bank/_mapping
GET /new_bank/_mapping
//新版本 es 7.x+ 写法:
POST _reindex
{
"source": {
"index": "bank"
},
"dest": {
"index": "new_bank"
}
}
// 旧版本 es 6.x 写法:
POST _reindex
{
"source": {
"index": "bank",
"type": "account"
},
"dest": {
"index": "new_bank"
}
}
// 执行结果
{
"took" : 223,
"timed_out" : false,
"total" : 1000,
"updated" : 0,
"created" : 1000,
"deleted" : 0,
"batches" : 1,
"version_conflicts" : 0,
"noops" : 0,
"retries" : {
"bulk" : 0,
"search" : 0
},
"throttled_millis" : 0,
"requests_per_second" : -1.0,
"throttled_until_millis" : 0,
"failures" : [ ]
}
// 查询数据,旧的数据 "_type" : "account"
GET /bank/_search
// 查询数据 ,查到 "_type" : "_doc" 。新版本都是默认为 “_doc”
GET /new_bank/_search
一个
tokenizer
(分词器)接收一个字符流,将之分割为独立的tokens
(词元,通常是独立的单词),然后输出tokens
流。
例如,whitespace tokenizer遇到空白字符时分割文本。它会将文本"Quick brown fox!"分割为[Quick,brown,fox!]。该
tokenizer
(分词器)还负责记录各个term
(词条)的顺序或position
位置(用于phrase
短语和word proximity
词近邻查询),以及term
(词条)所代表的原始word
(单词)的start
(起始)和end
(结束)的character offsets
(字符偏移量)(用于高亮显示搜索的内容)Elasticsearch
提供了很多内置的分词器,可以用来构建custom analyzers
(自定义分词器)。
注意:不能用默认 elasticsearch-plugin install xxx.zip 进行自动安装
因为版本对不上的话,elasticsearch会启动报错,无法启动。
ik分词器GitHub地址(选择对应es版本安装)
# 进入 es 容器内部 plugins 目录安装
$ docker exec -it [容器id或者容器名] /bin/bash
# 如果 docker 容器有挂载路径 也可以在,docker容器挂载的plugins目录安装
$ cd /mydata/elasticsearch/plugins
# 创建 ik目录
$ mkdir ik
$ cd ik
# 服务器内下载 ,也可以本地下载好后,移动到对应的安装目录
$ wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.17.1/elasticsearch-analysis-ik-7.17.1.zip
# zip 解压命令
$ unzip elasticsearch-analysis-ik-7.17.1.zip
# 删除 压缩包
$ rm -rf *.zip
# 授权
$ chmod -R 777 /mydata/elasticsearch/plugins/ik
# 进入 elasticsearch 容器内部
$ docker exec -it elasticsearch /bin/bash
# 可以确认是否安装好了分词器
cd ../bin
elasticsearch plugin list # 即可列出系统的分词器
# 重启 elasticsearch 容器
$ docker restart elasticsearch
GET bank/_analyze
{
"text": "我是中国人"
}
# 请观察结果中使用分词器 ik_smart
GET bank/_analyze
{
"analyzer": "ik_smart",
"text": "我是中国人"
}
# 请观察结果另外一个分词器ik_max_word
GET bank/_analyze
{
"analyzer": "ik_max_word",
"text": "我是中国人"
}
比如:将 自定义分词字段文件放到 nginx 上,es 通过配置 取 Nginx上的 字典数据
# docker 安装好Nginx,并启动
# 创建自定义分词字段文件
echo "哈利波特" >> /mydata/nginx/html/fenci/my_fenci.txt
# 验证:浏览器访问 http://192.168.56.10/fenci/my_fenci.txt。能正常读取
# 修改 修改`/usr/share/elasticsearch/plugins/ik/config/`中的 `iKAnalyzer.cfg-xml`
# 重启 elasticsearch 即可
$ docker restart elasticsearch
/usr/share/elasticsearch/plugins/ik/config
DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置comment>
<entry key="ext_dict">entry>
<entry key="ext_stopwords">entry>
<entry key="remote_ext_dict">http://192.168.56.10/fenci/my_fenci.txtentry>
properties>
1)、9300 端口 : TCP
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-elasticsearchartifactId>
dependency>
<dependency>
<groupId>org.springframework.datagroupId>
<artifactId>spring-data-elasticsearchartifactId>
<version>3.1.17.RELEASEversion>
<scope>compilescope>
<exclusions>
<exclusion>
<artifactId>jcl-over-slf4jartifactId>
<groupId>org.slf4jgroupId>
exclusion>
<exclusion>
<artifactId>log4j-coreartifactId>
<groupId>org.apache.logging.log4jgroupId>
exclusion>
exclusions>
dependency>
2)、9200端口:HTTP
JestClient:非官方,更新慢
RestTemplate:模拟发HTTP请求,ES很多操作需要自己封装,麻烦。
HttpClient: 理由同上
Java REST Client (Java High Level REST Client): 官方早期提供的 RestClient,在 7.15.0 版本中已弃用,现最新版8.x官方推荐使用 “Java API Client”的方式。如果原来旧项目中使用“Java REST Client”这种方式,想要升级改造使用最新的 Java API Client 的,官方也给出了解决方案,详见从高级 Rest 客户端迁移
Java REST 客户端官方说明文档 (7.17):Elasticsearch Java API Client(最新8.2) 7.15.0版本后使用这个,8.x普及。强烈推荐使用!!!
<project>
<properties>
<elasticsearch.version>7.17.1elasticsearch.version>
<jackson.version>2.12.3jackson.version>
properties>
<dependencies>
<dependency>
<groupId>co.elastic.clientsgroupId>
<artifactId>elasticsearch-javaartifactId>
<version>${elasticsearch.version}version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.12.3version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-coreartifactId>
<version>${jackson.version}version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-annotationsartifactId>
<version>${jackson.version}version>
dependency>
dependencies>
project>
数组存入 es中,默认是 被“扁平化”处理存储的。按照我们数组的定义结构,要想不匹配到错误的数据,应该设置为 nested
类型。
toString()
输出的问题目前最新版
elasticsearch-java( 8.2.2 )
版本的问题:就是所有的 DSL构造器
xxxBuilder
,均没有重写toString()
。导致想在开发自测中输出DSL
语句 到Kibana Dev Tools
中自测都不行了。目前想xxxBuilder
序列化成JSON输出,好得自己实现serialize(JsonGenerator generator, JsonpMapper mapper)
这个方法,麻烦…
然后比较滑稽的是,官方建议抛弃使用的
elasticsearch-rest-high-level-client
都有重写toString()
方法。
查了下github,发现该问题已有人提出,5月份还在优化中,暂时还没有最新的发布版本,我预测,可能会在 8.3版本被会修复吧。
GitHub问题描述与修复的地址:
如何打印一个可执行的DSL语句问题描述
添加 toString() 实现中…