Elastic Search 基本使用

中文文档地址:https://www.elastic.co/cn/what-is/elasticsearch

什么是Elastic Search

Elasticsearch 是一个开源的分布式 RESTful 搜索和分析引擎 , 适用于所有类型的数据,包括文本、数字、地理空间、结构化和非结构化数据。 Elasticsearch 以其简单的 REST 风格 API、分布式特性、速度和可扩展性而闻名,是 Elastic Stack 的核心组件;Elastic Stack 是适用于数据采集、充实、存储、分析和可视化的一组开源工具。人们通常将 Elastic Stack 称为 ELK Stack(代指 Elasticsearch、Logstash 和 Kibana),目前 Elastic Stack 包括一系列丰富的轻量型数据采集代理,这些代理统称为 Beats,可用来向 Elasticsearch 发送数据。

基本概念

Index(索引)

Elastic Search中的Index用来存放实际文档,数据的写入和查询是基于索引的。

Type(类型)

type建立在index之下,对index下的文档做虚拟分组;在es7以后版本,不再使用type,所有document文档数据直接存放在index下。

document(文档)

实际存放的数据,json格式文档。

Inverted Index (倒排索引)

通过文档ID,标记文档对应的所有关键词,这种方式是正向索引;而反过来,通过关键词,记录关键词出现过的文档,就是倒排索引。

数据类型

  • 基本类型,如 text, keyword, date, long, double, boolean, ip
  • 复合类型,如 object, nested
  • 特殊类型,如 geo_point, geo_shape, completion.

基本增删改查接口

_cat

_cat/nodes:查看所有节点;

_cat/health:查看es健康状况;

_cat/master:查看主节点;

_cat/indices:查看所有索引;

/_cat/allocation
/_cat/shards
/_cat/shards/{index}
/_cat/master
/_cat/nodes
/_cat/tasks
/_cat/indices
/_cat/indices/{index}
/_cat/segments
/_cat/segments/{index}
/_cat/count
/_cat/count/{index}
/_cat/recovery
/_cat/recovery/{index}
/_cat/health
/_cat/pending_tasks
/_cat/aliases
/_cat/aliases/{alias}
/_cat/thread_pool
/_cat/thread_pool/{thread_pools}
/_cat/plugins
/_cat/fielddata
/_cat/fielddata/{fields}
/_cat/nodeattrs
/_cat/repositories
/_cat/snapshots/{repository}
/_cat/templates

新增

PUT(POST)😕{index}/{type}/{id}: 新增OR更新;消息体是json

PUT:http://192.168.0.207:9200/idx1/user/1
{
    "_index": "idx1",   	// 所属索引
    "_type": "user", 		// 所属类型
    "_id": "1",				// id
    "_version": 1,			// 版本
    "result": "created",	// 返回结果
    "_shards": {			// 分区信息
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 0,			// 序列号,常用于乐观锁
    "_primary_term": 1		// 主分片
}

POST:/{index}/{type}: 新增,每次自动生成一个id;消息体是json

查询

GET:/{index}/{type}/{id}: 查看索引指定数据。

GET:http://192.168.0.207:9200/idx1/user/1
{
    "_index": "idx1",
    "_type": "user",
    "_id": "1",
    "_version": 2,
    "_seq_no": 1,
    "_primary_term": 1,
    "found": true,				// 查询结果
    "_source": {				// 实际查询到的数据
        "user_name": "hello es"
    }
}

修改

1,基本修改,和新增一致:PUT(POST)😕{index}/{type}/{id}: 新增OR更新;消息体是json
2,POST:_update更新;会检查文档是否需要更新。
POST {index}/{type}/{id}/_update

// http://192.168.0.207:9200/idx1/user/1/_update
// 消息体要带"doc"{"doc": { "user_name": "hello es2"}}
{
    "_index": "idx1",
    "_type": "user",
    "_id": "1",
    "_version": 3,			// 版本未变
    "result": "noop",		// 结果是 no operation
    "_shards": {
        "total": 0,
        "successful": 0,
        "failed": 0
    },
    "_seq_no": 2,			// seq未变
    "_primary_term": 1
}

3,乐观锁更新:
PUT:/{index}/{type}/{id}?if_seq_no={_seq_no}&if_primary_term={_primary_term};消息体是json

// http://192.168.0.207:9200/idx1/user/1?if_seq_no=1&if_primary_term=1
{
    "_index": "idx1",
    "_type": "user",
    "_id": "1",
    "_version": 3,				// 更新了版本号
    "result": "updated",		// 结果已更新
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 2,				// 更新了序列号
    "_primary_term": 1
}

删除

DELETE:/{index}/{type}/{id}: 删除指定索引下指定type下指定id的文档。
DELETE:/{index}: 删除指定索引。会删除索引下所有文档。

// http://192.168.0.207:9200/idx1
{
    "acknowledged": true
}

批量查询 mget

GET:/{index}/{type}/_mget: 查找指定索引指定类型下的文档。

// http://192.168.0.207:9200/idx1/user/_mget
// 参数体方式1
{
    "docs": [
        {
            "_id": "1",
            "_source": ["user_name","age"]
        },
        {
            "_id": "2"
        }
    ]
}
// 参数体方式2
{
   "ids":[1,2]
}

GET:/_mget: 查找指定索引指定类型下的文档。

// http://192.168.0.207:9200/_mget
// 参数体
{
    "docs": [
        {
            "_index": "idx1",
            "_type": "user",
            "_id": "1",
            "_source": ["user_name","age"]
        },
        {
            "_index": "idx1",
            "_type": "user",
            "_id": "2"
        }
    ]
}

批量操作 bulk

bulk的格式:
{action:{metadata}}\n
{requstbody}\n (请求体)

action:(行为),包含create(文档不存在时创建)、update(更新文档)、index(创建新文档或替换已用文档)、delete(删除一个文档)。
create和index的区别:如果数据存在,使用create操作失败,会提示文档已存在,使用index则可以成功执行。
metadata:(行为操作的具体索引信息),需要指明数据的_index、_type、_id。

和mget一致,可以在路径带上index和type直接指向指定索引和类型。

注意设置header请求头: Content-Type : application/json

// 方式一:带index和type
// http://192.168.0.207:9200/idx1/user/_bulk
{"index":{"_id":1}}
{"user_name": "es1","age": 40}
{"index":{"_id":2}}
{"user_name":"es2","age": 41}


// 方式二:不带index和type
// http://192.168.0.207:9200/_bulk
{"index":{"_index":"idx1","_type":"user","_id":1}}
{"user_name": "es1","age": 40}
{"index":{"_index":"idx1","_type":"user","_id":2}}
{"user_name":"es2","age": 41}


检索 _search

可以通过_search发送GET请求,检索文档。通过参数或者请求体指定过滤条件和排序规则。

// GET /bank/_search
// 方式1
// http://192.168.0.207:9200/idx1/_search?q=*&sort=age:desc
// 方式2
// http://192.168.0.207:9200/idx1/_search
{
  "query": { "match_all": {} },
  "sort": [
    { "age": "desc" }
  ]
}
// 返回结果:
{
    "took": 1,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 2,
            "relation": "eq"
        },
        "max_score": null,
        "hits": [
            {
                "_index": "idx1",
                "_type": "user",
                "_id": "2",
                "_score": null,
                "_source": {
                    "user_name": "es2",
                    "age": 41
                },
                "sort": [
                    41
                ]
            },
            {
                "_index": "idx1",
                "_type": "user",
                "_id": "1",
                "_score": null,
                "_source": {
                    "user_name": "es1",
                    "age": 40
                },
                "sort": [
                    40
                ]
            }
        ]
    }
}

Query DSL常用查询

基本语法

{

​ QUERY_NAME:{

​ ARGUMENT: VALUE,

​ ARGUMENT:VALUE,…

​ }

}
常用如下:

// match 分词
GET bank/_search
{
  "query": {
    "match": {
      "address": "mill road"
    }
  },
  "from": 0,
  "size": 10,
  "_source": ["firstname", "balance"]
}

// match_phrase 当成短语,不分词
GET bank/_search
{
  "query": {
    "match_phrase": {
      "address": "mill road"
    }
  }
}

// multi_match 多字段匹配;会分词
GET bank/_search
{
  "query": {
    "multi_match": {
      "query": "mill",
      "fields": ["address", "city"]
    }
  }
}

// bool 组合多条件 复合查询
GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "gender": "m"
          }  
        },
        {
          "match": {
            "address": "mill"
          }
        }
      ],
      "must_not": [
        {
          "match": {
            "age": 28
          }
        }
      ],
      "should": [
        {
          "match": {
            "lastname": "Wallace"
          }
        }
      ]
    }
  }
}

// filter 过滤(must_not)
GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "gender": "m"
          }  
        },
        {
          "match": {
            "address": "mill"
          }
        }
      ],
      "should": [
        {
          "match": {
            "lastname": "Wallace"
          }
        }
      ],
      "filter": {
        "range": {
          "balance": {
            "gte": 1000,
            "lte": 10000
          }
        }
      } 
    }
  }
}

// term (文本字段用must,精确值字段用term;term不做分词处理)
GET /bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "age": {
              "value": "38"
            }
          }
        },
        {
          "match": {
            "address": "Street"
          }
        }
      ]
    }
  }
}

聚合查询

ES里面,聚合查询就是根据搜索查询提供聚合数据,ES除了提供强大、快速的搜索,也提供了类似数据库的聚合查询分析。ES一次查询,将结果返回,并完成聚合分析。聚合可以进行多个维度,聚合分析可也以嵌套进行,类似多层分组。

聚合包含各种聚合方式,总体分指标聚合和桶聚合。具体各种聚合类型可以参考文档。(https://learnku.com/docs/elasticsearch73/7.3/article-11/6889)

使用样例:

// 聚合查询样例
// 聚合 group by + avg
GET bank/_search
{
  "size": 0,
  "aggs": {
    "group_by_keyword": {
      "terms": {
        "field": "state.keyword"
      },
      "aggs": {
        "average_balance": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  }
}

// 搜索并聚合
GET bank/_search
{
  "query": {
    "match": {
      "address": "mill"
    }
  },
  "aggs": {
    "agecount": {
      "terms": {
        "field": "age",
        "size": 10
      }
    },
    "avgbalance":{
      "avg": {
        "field": "balance"
      }
    }
  },
  "size": 0
}

// 查询+聚合+子聚合avg
GET bank/_search
{
  "query": {
    "match_all": {}
  }, 
  "size": 0,
  "aggs": {
    "group_by_keyword": {
      "terms": {
        "field": "state.keyword",
        "size": 10,
        "order": {
          "_count": "asc"
        }
      },
      "aggs": {
        "avgBalance": {
          "avg": {
            "field": "balance"
          }
        },
        "genderAgg": {
          "terms": {
            "field": "gender.keyword"
          },
          "aggs": {
            "avgBalance": {
              "avg": {
                "field": "balance"
              }
            }
          }
        }
      }
    }
  }
}

Mapping 映射

mapping是用来定义存储的文档及其属性是如何存储和索引的。

建索引,同时建mapping

// 新建索引并同步建mapping
PUT newidx1
{
  "mappings" : {
    "properties" : {
      "age" : {
        "type" : "integer"
      },
      "user_name" : {
        "type" : "text"
      }
    }
  }
}

给指定index新建mapping

// 已有index,增加mapping
PUT /testidx/_mapping
{
  "properties": {
    "test_property":{
      "type": "keyword",
      "index": false
    }
  }
}

更新索引的mapping

更新索引的mapping信息,只能通过创建新的索引,并对所有数据重新索引(_reindex)。

// reindex
POST _reindex
{
  "source": {
    "index": "bank"
  },
  "dest": {
    "index": "newbank"
  }
}

分词

所谓分词就是将完整的文本信息,分割为独立的词元,然后输出词元流。
ES默认带有很多分词器,但是这些分词器都不支持中文分词。一般使用开源分词器ik。
1,安装ik插件:直接通过官网找到下载.zip文件的地址。然后在linux中通过wget http***方式下载,然后解压到plugs下;重启es即可。
2,测试分词:

// ik_smart
// http://192.168.0.207:9200/_analyze
{
    "analyzer": "ik_smart",
    "text": "docker 安装ElasticSearch的中文分词器IK"
}
// ik_max_word 对比一下,这种分析器会组合更多的词元
// http://192.168.0.207:9200/_analyze
{
    "analyzer": "ik_max_word",
    "text": "docker 安装ElasticSearch的中文分词器IK"
}

3,扩展ik词库
ik词库两种模式提供的分词功能都能对中文文本进行分词,但是由于其默认使用的词库不一定满足所有要求,部分词元无法识别,可以通过扩展的方式让其识别。
修改es插件ik的配置文件:IKAnalyzer.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!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.0.207/words.text</entry>
        <!--用户可以在这里配置远程扩展停止词字典-->
        <!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>

4,指定默认分词器

// 创建索引时,就指定默认分词器
PUT newidx2
{
  "mappings" : {
    "properties" : {
      "age" : {
        "type" : "integer"
      },
      "user_name" : {
        "type" : "text"
      }
    }
  },
  "settings" : {
      "index" : {
        "analysis.analyzer.default.type": "ik_max_word"
    }
  }
}

spring boot 整合

es官方提供了对es rest api调用的客户端封装,只需要整合到spring boot项目就可以使用了。
1,添加依赖

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.10.1</version>
</dependency>

2,修改spring-boot-dependencies中管理的elasticsearch版本:在properties中重新指定版本。

    <properties>
  <elasticsearch.version>7.10.1</elasticsearch.version>
    </properties>

3,编写配置类

/**
 * ElasticSearch配置类
 */
@Configuration
public class ElasticSearchConfig {

    public static final RequestOptions COMMON_OPTIONS;
    static {
        RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
//        builder.addHeader("Authorization", "Bearer " + TOKEN);
//        builder.setHttpAsyncResponseConsumerFactory(
//                new HttpAsyncResponseConsumerFactory
//                        .HeapBufferedResponseConsumerFactory(30 * 1024 * 1024 * 1024));
        COMMON_OPTIONS = builder.build();
    }

    public RestHighLevelClient initRestHighLevelClient () {
        return new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("192.168.20.207", 9200, "http")));
    }
}

4,使用client调用接口操作es:
Java High Level REST Client接口文档参考:
https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.x/java-rest-high-supported-apis.html

    @Autowired
    RestHighLevelClient restHighLevelClient;

    private void esIndexApiCall() throws IOException {
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("user", "kimchy");
        jsonMap.put("postDate", new Date());
        jsonMap.put("message", "trying out Elasticsearch");
        IndexRequest indexRequest = new IndexRequest("posts")
                .id("1").source(jsonMap);
        IndexResponse indexResponse = restHighLevelClient.index(indexRequest, ElasticSearchConfig.COMMON_OPTIONS);
    }

小结

ElasticSearch的简单使用,先总结到这里,其全文检索的实现原理待再进一步了解,先用起来!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值