官方文档:[开始搜索|弹性搜索指南 7.5] |弹性的 (elastic.co)
ES(一):ES基本概念和原理简单介绍https://blog.51cto.com/u_14286115/3328651
版本对比:(13条消息) Elasticsearch各个版本重要特性_elasticsearch常用版本_坚持是一种态度的博客-CSDN博客
mysql更适合做数据的持久化处理,增删改查操作。El更适合做数据的检索分析。可以秒级在商品中检索出所需要的信息。
基本概念
Index(数据库) 动词,相当于 MySQL 中的 insert; 名词,相当于 MySQL中的 Database
Type(表) 在 Index(索引)中,可以定义一个或多个类型。 类似于 MySQL 中的 Table;每一种类型的数据放在一起
注意:7.0版本之后,type类型被移除,7.0检索的时候type可带可不带,8.0不允许带
移除原因:在同一index中,ES中不同type下名称相同的filed最终在Lucene中的处理方式是一样的,两个不同type下的两个user_name,在ES同一个索引下其实被认为是同一个filed,你必须在两个不同的type中定义相同的filed映射。
去掉type能够使数据存储在独立的index中,这样即使有相同的字段名称也不会出现冲突,就像ElasticSearch出现的第一句话一样“你知道的,为了搜索····”,去掉type就是为了提高ES处理数据的效率。
查询时,我们可以将所有的type的值都使用_doc 如:查询索引consumer中id为1的数据。 GET /consumer/ _ doc/1
Document(记录) 保存在某个索引(Index)下,某种类型(Type)的一个数据(Document),文档是 JSON 格 式的,Document 相当于Mysql一条记录
mapping(表结构):mapping是对索引库中的索引字段及其数据类型进行定义,ES默认动态创建索引和索引类型的mapping。
倒排索引
往ES中存储数据的时候,可以使用分词的方式。拿存储1:红海行动和5:特工红海特别探索为例。
红海行动可以拆分成,红海和行动。将红海行动存储到ES中,将红海和行动这两个词分别存放到ES的倒排索引中。
特工红海特别探索可以拆分成特工,红海,特别,探索。然后存储到倒排索引中,倒排索引中记录数据在ES中存放的位置。
查询红海行动时,会将红海行动分词,分成红海和行动,然后去倒排索引中查找
核心概念
1、分片(shard):
如果我们的索引数据量很大,超过硬件存放单个文件的限制,就会影响查询请求的速度,Es引入了分片技术。一个分片本身就是一个完成的搜索引擎,文档存储在分片中,而分片会被分配到集群中的各个节点中,随着集群的扩大和缩小,ES会自动的将分片在节点之间进行迁移,以保证集群能保持一种平衡。分片有以下特点:
2、副本(replica):
副本(replica shard)就是shard的冗余备份,它的主要作用:
ES的特性:
速度快、易扩展、弹性、灵活、操作简单、多语言客户端、X-Pack、hadoop/spark强强联手、开箱即用。
创建挂载目录
mkdir -p /mydata/elasticsearch/config
mkdir -p /mydata/elasticsearch/data
echo “http.host: 0.0.0.0” >> /mydata/elasticsearch/config/elasticsearch.yml
创建docker 容器
# 创建配置文件目录
mkdir -p /opt/docker/mid_elasticsearch_test/config
# 创建数据目录
mkdir -p /opt/docker/mid_elasticsearch_test/data
# 将/mydata/elasticsearch/文件夹中文件都可读可写
chmod -R 777 /opt/docker/mid_elasticsearch_test
# 配置任意机器可以访问 elasticsearch
echo "http.host: 0.0.0.0" >/opt/docker/mid_elasticsearch_test/config/elasticsearch.yml
docker run --name elasticsearch_test -p 9200:9200 -p 9300:9300 --restart=always \
-e "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms64m -Xmx512m" \
-v /opt/docker/mid_elasticsearch_test/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /opt/docker/mid_elasticsearch_test/data:/usr/share/elasticsearch/data \
-v /opt/docker/mid_elasticsearch_test/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.4.2
# Docker 开机自启,所以 ES 现在也是开机自启
docker update elasticsearch --restart=always
# 参数解读
● -p 9200:9200 -p 9300:9300:向外暴露两个端口,9200用于HTTP REST API请求,9300 ES 在分布式集群状态下 ES 之间的通信端口;
● -e "discovery.type=single-node":es 以单节点运行
● -e ES_JAVA_OPTS="-Xms64m -Xmx512m":设置启动占用内存,不设置可能会占用当前系统所有内存,制ES所占用的内存大小,测试服务器使用。
● -v:挂载容器中的配置文件、数据文件、插件数据到本机的文件夹;
● -d elasticsearch:7.6.2:指定要启动的镜像
# 附:
如果要修改ES的内存大小,可以停掉ES,删除容器,再重新创建一个容器,因为ES启动的时候进行了目录挂载,因此不会产生数据丢失。
问题:es容器闪退
docker pull kibana:7.4.2 可视化检索数据
docker run --name kibana -e ELASTICSEARCH_HOSTS=http://XX.XX.XX:9200 -p 5601:5601 -d kibana:7.4.2
http://XX.XX.XX:9200 一定改为自己虚拟机的地址,表示要链接的es地址。
查询、更新时,我们可以将所有的type的值都使用_doc 如:查询索引consumer中id为1的数据。 GET /consumer/ _ doc/1
es的所有请求,都封装成了restapi,我们查询数据发送请求即可。
GET /_ cat/nodes:查看所有节点
GET /_cat/health:查看 es 健康状况
GET / _ cat/master:查看主节点
GET /_cat/indices:查看所有索引 show databases
保存一个数据,保存在哪个索引的哪个类型下,指定用哪个唯一标识 .
PUT/POST customer/external/1;在 customer 索引下的 external 类型下保存 1 号数据
es存储的数据都是json对象。
# 已淘汰,执行后会提示[types removal] Specifying types in document index requests is deprecated, use the typeless endpoints instead (/{index}/_doc/{id}, /{index}/_doc, or /{index}/_create/{id}).
PUT customer/external/1
{
"name": "John Doe"
}
# 最新 以下三种方式均可
POST customer/_create/6 id 为6
{
"name": "张三"
}
POST customer/_doc/4 id 为 4
{
"name": "张三"
}
POST customer/_doc id随机生成
{
"name": "张三"
}
结果:不管使用_doc还是_create,_type的结果都是_doc
{
"_index" : "customer",
"_type" : "_doc",
"_id" : "10",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 8,
"_primary_term" : 1
}
PUT 和 POST 都可以,
POST 新增。如果不指定 id,会自动生成 id。指定 id 就会修改这个数据,并新增版本号
PUT 可以新增可以修改。PUT 必须指定 id;由于 PUT 需要指定 id,我们一般都用来做修改
操作,不指定 id 会报错。
put新增:
新增:
GET customer/external/1
淘汰:GET customer/external/1
最新:GET customer/_doc/1 type统一用_doc
{ "_index": "customer", //在哪个索引
"_type": "external", //在哪个类型
"_id": "1", //记录 id
"_version": 2, //版本号
"_seq_no": 1, //并发控制字段,每次更新就会+1,用来做乐观锁
"_primary_term": 1, //同上,主分片重新分配,如重启,就会变化
"found": true, "_source": { //真正的内容
"name": "John Doe"
}
}
_seq_no 表示乐观锁
假如A,B两个请求都过来了,都要修改同一条数据,如果A将数据修改后,那么_seq_no 会发生变化,由1变为2,B修改的时候,传递一个查询条件,_ seq_no 为1,那么此时B就不发生修改。
假如此时我同时发送两次更新请求:
A:http://39.XX.XX.XX:9200/customer/external/1?if_seq_no=2&if_primary_term=1 修改name = 1
此时_seq_no = “_seq_no”: 3,
B也发送http://39.XX.XX.XX:9200/customer/external/1?if_seq_no=2&if_primary_term=1 请求时,因为seq_no此时已变成3,因此修改不成功。
post带update
POST customer/external/1/_update
{
"doc":{ "name": "John Doew"}
}
post携带update的时候,必须带doc
更新之后,再次更新时,如果最新的数据和原来的数据一样,那么什么都不进行更新。
直接使用update
PUT customer/external/1
{
"name": "John Doe"
}
不同点:
POST 操作会对比源文档数据,如果相同不会有什么操作,文档 version 不增加
PUT 操作总会将数据重新保存并增加 version 版本;
带_update 对比元数据如果一样就不进行任何操作。
看场景;
对于大并发更新,不带 update;
对于大并发查询偶尔更新,带 update;对比更新,重新计算分配规则。
更新同时增加属性
POST customer/external/1/_update
{
"doc": { "name": "Jane Doe", "age": 20 }
}
PUT 和 POST 不带_update 也可以
删除文档:DELETE customer/external/1
删除索引:DELETE customer
没有删除类型的操作。
批量添加数据
POST customer/external/_bulk
{"index":{"_id":"1"}}
{"name": "John Doe" }
{"index":{"_id":"2"}}
{"name": "Jane Doe" }
语法格式
语法格式:
{ action: { metadata }}
{ request body }
{ action: { metadata }}
{ request body }
混合操作
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"} }
{ "doc" : {"title" : "My updated blog post"} }
G:\ComputerStudy\openitem\gulimallallfiles\课件和文档\高级篇\课件\es文件.txt
POST bank/account/_bulk
curl -H "Content-Type: application/json" -XPOST "localhost:9200/bank/_bulk?pretty&refresh" --data-binary "@/文件路径"
注意:如果是官网下载的json文件,要打开删除最后一个空行,再按回车添加一个空行。官方文件:https://raw.githubusercontent.com/elastic/elasticsearch/7.5/docs/src/test/resources/accounts.json
问题:[使用ElasticSearch在bulk导入json数据时,The bulk request must be terminated by a newline \n]_BackToMeNow的博客-CSDN博客_bulkrequest写入json
[查询和筛选上下文|弹性搜索指南 7.5] |弹性的 (elastic.co)
ES 支持两种基本方式检索 :
一个是通过使用 REST request URI 发送搜索参数(uri+检索参数)
GET /bank/_search //查询bank索引下的所有数据
GET bank/_search?q=*&sort=account_number:asc
q=* :查询所有
sort = account_number:asc 排序方式
一个是通过使用 REST request body 来发送它们(uri+请求体)
GET /bank/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"age": "desc"
},
{
"account_number": "asc"
}
]
}
返回结果:
具体记录:
分页检索
For example, the following request gets hits 10 through 19:
GET /bank/_search
{
"query": { "match_all": {} },
"sort": [
{ "account_number": "asc" }
],
"from": 10,
"size": 10
}
https://www.elastic.co/guide/en/elasticsearch/reference/7.5/getting-started-search.html)
相关性分数
默认情况下,Elasticsearch 会按相关性对匹配的搜索结果进行排序 分数,用于衡量每个文档与查询的匹配程度。
相关性分数在查询结果中返回,级别越高,文档越相关。_score
查询上下文
查询子句根据条件来决定文档匹配,还会计算字段中的相关性分数。
筛选上下文
回答查询子句当前记录是否符合,是否达到计算分数要求。
GET /_search
{
"query": { 该参数指示查询上下文。query
"bool": { must两个子句用于查询上下文, 这意味着它们用于对每个文档进行评分比赛。boolmatch
"must": [
{ "match": { "title": "Search" }},
{ "match": { "content": "Elasticsearch" }}
],
"filter": [ 该参数指示筛选器上下文。其 and 子句用于筛选器上下文。他们会过滤掉不匹配的文件,但它们不会影响匹配文档的分数。filtertermrange
{ "term": { "status": "published" }},
{ "range": { "publish_date": { "gte": "2015-01-01" }}}
]
}
}
}
基本语法格式
GET bank/_search
{
"query": {
"match_all": {}
},
"from": 0,
"size": 5,
"sort": [
{
"account_number": {
"order": "desc"
},
"balance": {
"order": "asc"
}
}
]
}
# match_all 查询类型【代表查询所有的所有】,es中可以在query中组合非常多的查询类型完成复杂查询;
# from+size 限定,完成分页功能;从第几条数据开始,每页有多少数据
# sort 排序,多字段排序,会在前序字段相等时后续字段内部排序,否则以前序为准;
基本返回结果
语法结构
Elasticsearch 提供了一个可以执行查询的 Json 风格的 DSL(domain-specific language 领域特 定语言)。这个被称为 Query DSL。
查询语句 的典型结构:
如果是针对某个字段:
和 match 一样。匹配某个属性的值。全文检索字段用 match,其他非 text 字段匹配用 term。
Avoid using the
term
query fortext
fields.避免使用 term 查询文本字段
By default, Elasticsearch changes the values of
text
fields as part of analysis. This can make finding exact matches fortext
field values difficult.默认情况下,Elasticsearch 会通过analysis分词将文本字段的值拆分为一部分,这使精确匹配文本字段的值变得困难。
To search
text
field values, use thematch
query instead.如果要查询文本字段值,请使用 match 查询代替。
使用match
使用term
GET bank/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"age": {
"value": "28"
}
}
},
{
"match": {
"address": "990 Mill Road"
}
}
]
}
}
}
普通match
keyword
短语匹配
bool 用来做复合查询: 复合语句可以合并 任何 其它查询语句,包括复合语句,了解这一点是很重要的。这就意味 着,复合语句之间可以互相嵌套,可以表达非常复杂的逻辑。
匹配与其他布尔组合匹配的文档的查询。类型:BooleanQuery
Occur | Description |
---|---|
must |
The clause (query) must appear in matching documents and will contribute to the score. 子句必须出现在匹配的文档中,并且贡献分数 |
filter |
The clause (query) must appear in matching documents. However unlike the score of the query will be ignored. Filter clauses are executed in filter context, meaning that scoring is ignored and clauses are considered for caching.must 子句(查询)必须出现在匹配的文档中。 |
should |
The clause (query) should appear in the matching document. 子句应该出现在匹配文档中 |
must_not |
The clause (query) must not appear in the matching documents. Clauses are executed in filter context meaning that scoring is ignored and clauses are considered for caching. Because scoring is ignored, a score of for all documents is returned.0 子句(查询)不得出现在匹配项中 文件。 |
在boolean查询中,must
, should
和must_not
元素都被称为查询子句 。 文档是否符合每个“must”或“should”子句中的标准,决定了文档的“相关性得分”。 得分越高,文档越符合您的搜索条件。 默认情况下,Elasticsearch 返回根据这些相关性得分排序的文档。
“must_not”子句中的条件被视为“过滤器”。
它影响文档是否包含在结果中,但不影响文档的评分方式。还可以显式地指定任意过滤器来包含或排除基于结构化数据的文档。
POST _search
{
"query": {
"bool" : {
"must" : {
"term" : { "user" : "kimchy" }
},
"filter": {
"term" : { "tag" : "tech" }
},
"must_not" : {
"range" : {
"age" : { "gte" : 10, "lte" : 20 }
}
},
"should" : [
{ "term" : { "tag" : "wow" } },
{ "term" : { "tag" : "elasticsearch" } }
],
"minimum_should_match" : 1,
"boost" : 1.0
}
}
}
minimum_should_match:最小匹配度,必须紧跟should,用参数指定数字或返回文档的子句百分比必须匹配。
不是很明白,之后需要了的话再细看。
参考文章(18条消息) elasticsearch中minimum_should_match的一些理解_xiao_jun_0820的博客-CSDN博客_minimumnumbershouldmatch
必须达到 must 列举的所有条件
GET bank/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"address": "mill"
}
},
{
"match": {
"gender": "M"
}
}
]
}
}
}
should:应该达到 should 列举的条件,如果达到**会增加相关文档的评分,并不会改变查询的结果。**如果 query 中只有 should 且只有一种匹配规则,那么 should 的条件就会被作为默认匹配条件而去改变查询结果
GET bank/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"address": "mill"
}
},
{
"match": {
"gender": "M"
}
}
],
"should": [
{
"match": {
"address": "lane"
}
}
]
}
}
}
必须不是指定的情况
GET bank/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"address": "mill"
}
},
{
"match": {
"gender": "M"
}
}
],
"should": [
{
"match": {
"address": "lane"
}
}
],
"must_not": [
{
"match": {
"email": "baluba.com"
}
}
]
}
}
}
address 包含 mill,并且 gender 是 M,如果 address 里面有 lane 最好不过,但是 email 必须不包含 baluba.com
filter 对结果进行过滤,使用方法和must一样,但是没有相关性得分。
GET bank/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"address": "mill"
}
}
],
"filter": {
"range": {
"balance": {
"gte": "10000",
"lte": "20000"
}
}
}
}
}
}
# 这里先是查询所有匹配 address 包含 mill 的文档,
# 然后再根据 10000<=balance<=20000 进行过滤查询结果
GET bank/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"address": "mill"
}
},
{
"match": {
"gender": "M"
}
}
],
"should": [
{
"match": {
"address": "lane"
}
}
],
"must_not": [
{
"match": {
"email": "baluba.com"
}
}
],
"filter":{
"range": {
"age": {
"gte": 18,
"lte": 30
}
}
}
}
}
}
**聚合提供了从数据中分组和提取数据的能力。(mysql的聚合函数)**最简单的聚合方法大致等于 SQL GROUP BY 和 SQL 聚合函数。
在 Elasticsearch 中,您有执行搜索返回 hits(命中结果),并且同时返 回聚合结果,把一个响应中的所有 hits(命中结果)分隔开的能力。
这是非常强大且有效的, 您可以执行查询和多个聚合,并且在一次使用中得到各自的(任何一个的)返回结果,使用 一次简洁和简化的 API 来避免网络往返。
GET bank/_search
{
"query": {
"match": {
"address": "mill"
}
},
"aggs": { //聚合:求年龄的分布情况 。 如年龄38的有多少人。
"group_by_state": { //聚合名称
"terms": { //分布情况,使用terms
"field": "age" //聚合字段
}
},
"ageavg": { //聚合:求年龄的平均值
"avg": {
"field": "age"
}
}
},
"size":0 //不显示人的详情。
}
GET bank/_search
{
"query": {
"match_all": {}
},
"aggs": {
"ageAgg": {
"terms": {
"field": "age"
},
"aggs": {
"balance_avg": {
"avg": {
"field": "balance"
}
}
}
}
},
"size": 0
}
分析:
GET bank/_search
{
"query": {
"match_all": {}
},
"aggs": {
"ageAgg": {
"terms": {
"field": "age",
"size": 100
},
"aggs": {
"genderAgg": {
"terms": {
"field": "gender.keyword", //因为gender是文本类型。具体见下文报错。
"size": 2
},
"aggs": {
"balanceAvg": {
"avg": {
"field": "balance"
}
}
}
},
"ageAggBalanceAvg": {
"avg": {
"field": "balance"
}
}
}
}
}
}
[Quick start | Elasticsearch Guide 8.1] | Elastic
Maping是用来定义一个文档(document),以及它所包含的属性(field)是如何存储和索引的。
比如:使用maping来定义:
查看mapping信息
GET bank/_mapping
{
"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
}
}
}
}
}
}
}
[Field datatypes | Elasticsearch Guide 7.5] | Elastic
创建映射操作
创建索引并指定属性的映射规则(相当于新建表并指定字段和字段类型)
PUT /my_index
{
"mappings": {
"properties": {
"age": {
"type": "integer"
},
"email": {
"type": "keyword"
},
"name": {
"type": "text"
}
}
}
}
结果:
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "my_index"
}
https://www.elastic.co/guide/en/elasticsearch/reference/7.x/explicit-mapping.html#add-field-mapping
PUT /my_index/_mapping
{
"properties": {
"employee-id": {
"type": "keyword",
"index": false
}
}
}
# 这里的 "index": false,表明新增的字段不能被检索。默认是true
# https://www.elastic.co/guide/en/elasticsearch/reference/7.5/mapping-index.html
结果:
{
"acknowledged" : true
}
https://www.elastic.co/guide/en/elasticsearch/reference/7.x/explicit-mapping.html#view-mapping
GET /my_index/_mapping
# 查看某一个字段的映射
GET /my_index/_mapping/field/employee-id
结果:
{
"my_index" : {
"mappings" : {
"properties" : {
"age" : {
"type" : "integer"
},
"email" : {
"type" : "keyword"
},
"employee-id" : {
"type" : "keyword",
"index" : false
},
"name" : {
"type" : "text"
}
}
}
}
}
# index false 表示不能被索引找到
https://www.elastic.co/guide/en/elasticsearch/reference/7.x/explicit-mapping.html#update-mapping
对于已经存在的字段映射,我们不能更新。更新必须创建新的索引,进行数据迁移。
Changing an existing field could invalidate data that’s already indexed.
迁移方式分为两种,一种是7和7之后去掉type的情况,一种是包含type 迁移的情况。
POST reindex [固定写法]
{
"source":{
"index":"twitter"
},
"dest":{
"index":"new_twitters"
}
}
POST reindex [固定写法]
{
"source":{
"index":"twitter",
"twitter":"twitter"
},
"dest":{
"index":"new_twitters"
}
}
对于我们的测试数据,是包含 type 的索引 bank。
现在我们创建新的索引 newbank 并修改一些字段的类型来演示当需要更新映射时的数据迁移操作。
当前bank的文档类型
{
"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
}
}
}
}
}
}
}
创建新索引 newbank 并修改字段类型
POST _reindex
{
"source": {
"index": "bank",
"type": "account"
},
"dest": {
"index": "newbank"
}
}
结果:
#! Deprecation: [types removal] Specifying types in reindex requests is deprecated.
{
"took" : 269,
"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" : [ ]
}
一个tokenizer(分词器)接收一个字符流,将之分割为独立的tokens(词元,通常是独立的单词),然后输出tokens流。
例如:whitespace tokenizer遇到空白字符时分割文本。它会将文本“Quick brown fox!”分割为[Quick,brown,fox!]。
该tokenizer(分词器)还负责记录各个terms(词条)的顺序或position位置(用于phrase短语和word proximity词近邻查询),以及term(词条)所代表的原始word(单词)的start(起始)和end(结束)的character offsets(字符串偏移量)(用于高亮显示搜索的内容)。
elasticsearch提供了很多内置的分词器,可以用来构建custom analyzers(自定义分词器)。
POST _analyze
{
"analyzer": "standard",
"text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}
结果:
{
"tokens" : [
{
"token" : "the",
"start_offset" : 0,
"end_offset" : 3,
"type" : "" ,
"position" : 0
},
{
"token" : "2",
"start_offset" : 4,
"end_offset" : 5,
"type" : "" ,
"position" : 1
},
{
"token" : "quick",
"start_offset" : 6,
"end_offset" : 11,
"type" : "" ,
"position" : 2
},
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
}
默认的分词器一般都是针对于英文,对于中文我们需要安装额外的分词器来进行分词。
没有中文分词器
GET _analyze
{
"analyzer": "ik_max_word",
"text":"蔡徐坤"
}
# 进入挂载的插件目录 /opt/docker/mid_elasticsearch_test/plugins
cd /opt/docker/mid_elasticsearch_test/plugins
# 安装 wget 下载工具
yum install -y wget
# 下载对应版本的 IK 分词器(这里是7.4.2)
wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.4.2/elasticsearch-analysis-ik-7.4.2
# 进入容器内部
docker exec -it elasticsearch /bin/bash
# 查看 es 插件目录
ls /usr/share/elasticsearch/plugins
# 可以看到 elasticsearch-analysis-ik-7.4.2.zip
这里对于默认词库中没有的词,不会有词语的组合,所以我们可以通过配置自定义词库或远程词库来实现对词库的扩展。
安装nginx
# 创建初始nginx容器,目的复制默认配置
docker run -p 80:80 --name nginx -d nginx:1.10
# 将容器呢欸文件拷贝到当前目录:
docker cp nginx:/etc/nginx .
# 修改文件名称nginx 为conf,并移动到/opt/docker/mid_nginx_test/nginx目录下
mv nginx conf
mv conf/ /opt/docker/mid_nginx_test
# 直接删除旧的容器
docker rm -f nginx
# 启动新的容器
docker run -p 80:80 --name nginx-test -v /opt/docker/mid_nginx_test/nginx/html:/usr/share/nginx/html -v /opt/docker/mid_nginx_test/nginx/logs:/var/log/nginx -v /opt/docker/mid_nginx_test/nginx/conf:/etc/nginx -d nginx:1.10
配置远程词库
进入:vi /opt/docker/mid_elasticsearch_test/plugins/ik/config/IKAnalyzer.cfg.xml
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://82.157.236.113/fenci.txtentry>
properties>
重启es:docker restart elasticsearch
测试分词效果:
GET _analyze
{
"analyzer": "ik_max_word",
"text":"蔡徐坤"
}
结果:
{
"tokens" : [
{
"token" : "蔡徐坤",
"start_offset" : 0,
"end_offset" : 3,
"type" : "CN_WORD",
"position" : 0
}
]
}
解决方案:在聚合的terms中添加size字段。
GET bank/_search
{
"size":0, # 只返回聚合字段age的信息
"aggs": {
"group_by_age": {
"terms": {
"field": "age",
"size":100
}
}
}
}
因为es中数据量巨大,因此必须通过size限制,进而防止OOM。