【学习】ElasticSearch
目录
一、ElasticSearch简介
Elasticsearch(简称ES)是一款开源的、用Java实现的、基于Apache Lucene、RESTful协议的、分布式的、高性能、高可用搜索引擎,ES可以让你近实时快速存储、搜索、分析大量数据,并在秒级内返回给你搜索结果。它能够实现快速搜索响应,因为它不是直接搜索文本text,而是搜索索引index,它使用基于文档document而不是表table和schema的结构。简单来讲,可以将Elasticsearch视为一个可以处理JSON请求并返回JSON数据的服务器。
多年来,Elasticsearch及其周围壮大的生态系统(称为“Elastic Stack”,以ES 、Logstash、Kibana为核心)已被用于越来越多的场景,从简单的网站或文档搜索,到收集和分析日志数据,再到数据分析和可视化的商业智能工具。
- 搜索应用
- 推荐应用
- 二级索引,如CMS Content
- 存储和分析日志
- 机器学习、地理信息、生物信息存储和处理数据
- …
二、基本原理
2.1 字段Field
2.2 文档Document
Elasticsearch 是面向文档的,文档是所有可搜索数据的最小单元。ES中的文档就像MySQL中的一条记录,ES的文档会被序列化成JSON格式,保存在ES中。JSON对象由字段组成,字段就相当于MySQL的列。
2.3 类型Type
类型就相当于MySQL里的表,MySQL一个数据库下面有很多表,一个索引下面有很多Type,新版本后类型的概念逐渐废弃,一个索引下定义多个mappings来代替类型概念。
2.4 索引Index
索引就相当于MySQL里的数据库,某种相似特征的文档集合,不同特征的文档不应该放在同一个索引下。
ES | MySQL |
---|---|
字段 | 列 |
文档Document | 一行数据Row |
类型Type | 表Table |
索引Index | 数据库Database |
字段是文档的某个属性,文档是可被索引的基本实体,类型用于区分索引中文档的类型,索引是包含有相似特征的文档集合。
字段Field
"name":"duffy"
文档Document
{
"name":"duffy",
"age":"29",
"sex":"male"
}
类型Type
"person":{
"properties:"{
"name":{
"type":"keyword",
},
"age":{
"type":"integer",
},
"sex":{
"type":"bool"
}
}
}
三、基本API
curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'
- :适当的 HTTP 方法或动词。 例如,GET,POST,PUT,HEAD 或 DELETE
- :http 或 https。 如果你在 Elasticsearch 前面有一个 HTTPS 代理,或者你使用 Elasticsearch 安全功能来加密 HTTP 通信,请使用后者
- :Elasticsearch 集群中任何节点的Host。
- :运行 Elasticsearch HTTP 服务的端口,默认为9200。
- :API 端点,可以包含多个组件,例如_cat、 _cluster/stats 或 _nodes/stats/jvm
- <QUERY_STRING>:任何可选的查询字符串参数。
- q:指定查询字符串,用于全文搜索。q=example,指定对字符串"example"进行全文搜索,或者也可以用q=user:duffy,user字段中属性为duffy。
- sort:指定要对搜索结果进行排序的字段和排序顺序。sort=published:desc,按照 published 字段降序排序。
- from和size:指定要返回的搜索结果的大小和偏移量,用于进行分页。from=10&size=5。
- fields和_source:指定要返回的文档字段,可以使用通配符来匹配多个字段。fields=title,body&_source=false,指定要返回的文档字段只有 title 和 body,不返回 _source 字段中的原始文档内容。
- filter_path:指定要检索的字段,使用点号表示镶嵌。filter_path=_source.title,_source.tags,只检索title和tags字段。
- pretty:将漂亮地打印 JSON 响应以使其更易于阅读。pretty=true。
- :JSON 编码的请求正文(如有必要)
3.1 创建index
curl -XPUT 'http://foody.es.toc.test.sz.alibaba.io:31625/foody_test_id_filter_option_index_v1'
3.2 删除index
curl -XDELETE 'http://foody.es.toc.test.sz.shop.io:31625/foody_test_id_filter_option_index'
3.3 查看index
curl -XGET 'http://foody.es.toc.test.sz.shop.io:31625/_cat/indices'
结果
green open foody_test_sg_tip_index_v1 9ZpTFSqwTgO9qyuCqhwjxA 1 1 0 0 566b 283b
green open foody_test_id_driver_profile_v2 hOkY5Tv0TmOBgKrv5G7jSA 1 1 1470 63 3.4mb 1.4mb
green open foody_uat_my_drivertiering_tier_scheme_index_v1 G0Lq-kRfSoSBGUnHtewX-g 1 1 15 3 65.3kb 49.6kb
green open foody_test_vn_spx_driver_settlement_index_v1 -3C0T1YbSSGv8cj6bqIpsA 1 1 70 7 153.6kb 76.8kb
green open foody_test_th_record_index_v1 KJ5XoBklTqSrdSVP4LjKoA 1 1 29734 0 10.9mb 5.4mb
green open foody_test_tw_driver_quit_index_v1 89IizxC_QmK13FvhxTpxUg 1 1 0 0 566b 283b
3.4 创建document
curl -PUT 'http://foody.es.toc.test.sz.shop.io:31625/foody_test_id_filter_option_index_v1/_doc/1'
curl -POST 'http://foody.es.toc.test.sz.shop.io:31625/foody_test_id_filter_option_index_v1/_doc' -H 'Content-Type: application/json' -d '
{
"name":"optiontest1",
"description":"this is a description",
"priority":1,
"status":2,
"effective_time":1687583448000,
"expire_time":1687583450000
}
'
结果
{
"_index": "foody_test_id_filter_option_index_v1",
"_type": "_doc",
"_id": "1",
"_version": 1,
"created": true
}
批量jijian建susuo索引
POST /my_store/products/_bulk
3.5 更新document
curl -XPOST 'http://foody.es.toc.test.sz.shop.io:31625/foody_test_id_buyer_content_index_v1/_doc/1/_update' -H 'Content-Type: application/json' -d '
{
"doc": {
"description":"this is a description V2"
}
}
'
结果
{
"_index" : "foody_test_id_buyer_content_index_v1",
"_type" : "_doc",
"_id" : "1",
"_version" : 2,
"created": false //相同的索引、类型和ID都已经存在
}
注意ES中文档是不可改变的,不能修改它们,如果想要更新现有的文档,需要重建索引或者替换
3.6 删除document
curl -DELETE 'http://foody.es.toc.test.sz.shop.io:31625/foody_test_id_buyer_content_index_v1/_doc/1'
结果
{
"found" : true,
"_index" : "foody_test_id_buyer_content_index_v1",
"_type" : "_doc",
"_id" : "1",
"_version" : 3
}
3.7 查看document
curl -GET 'http://foody.es.toc.test.sz.shop.io:31625/foody_test_id_buyer_content_index_v1/_doc/1'
结果
{
"_index" : "foody_test_id_filter_option_index_v1",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : {
"title": "My first blog entry",
"text": "Just trying this out...",
"date": "2014/01/01"
}
}
------
{
"_index" : "foody_test_id_filter_option_index_v1",
"_type" : "_doc",
"_id" : "2",
"found" : false
}
3.8 查看mapping
curl -XGET 'http://foody.es.toc.test.sz.shop.io:31625/foody_test_id_buyer_content_index_v1/_mapping'
结果
{
"foody_test_id_buyer_content_index_v1":{
"mappings":{
"properties":{
"banner_type":{
"type":"long"
},
"cities":{
"type":"keyword",
"doc_values":false
},
"create_time":{
"type":"long"
},
"creator":{
"type":"keyword",
"index":false,
"doc_values":false
},
"description":{
"type":"keyword",
"index":false,
"doc_values":false
},
"effective_time":{
"type":"long",
"doc_values":false
},
"expire_time":{
"type":"long",
"doc_values":false
},
"frequency":{
"type":"long"
},
"id":{
"type":"long"
},
"image":{
"type":"keyword",
"index":false,
"doc_values":false
},
"link":{
"type":"keyword",
"index":false,
"doc_values":false
},
"listing_type":{
"type":"long"
},
"location_group_ids":{
"type":"keyword",
"doc_values":false
},
"name":{
"type":"keyword",
"index":false,
"doc_values":false
},
"platform_link":{
"type":"text",
"fields":{
"keyword":{
"type":"keyword",
"ignore_above":256
}
}
},
"position":{
"type":"long",
"doc_values":false
},
"priority":{
"type":"short"
},
"role_access":{
"type":"keyword",
"doc_values":false
},
"status":{
"type":"byte",
"doc_values":false
},
"store_ids":{
"type":"keyword",
"index":false,
"doc_values":false
},
"time_ranges":{
"type":"keyword",
"index":false,
"doc_values":false
},
"title":{
"type":"keyword",
"index":false,
"doc_values":false
},
"type":{
"type":"byte",
"index":false,
"doc_values":false
},
"update_time":{
"type":"long",
"index":false,
"doc_values":false
},
"working_group":{
"type":"short"
}
}
}
}
}
字段中常见属性解释:
- type:字段类型,如 text、keyword、date、integer、float、boolean 等。
– text类型是一个可以被分词的的字符串,适用于全文搜索和模糊查询等场景。
– keyword类型是一个非分词的精确值字段,适用于需要按照整个字符串进行匹配的场景。 - analyzer:文本分析器,控制需要进行分词策略和指定使用哪个分词器。默认的分词器是标准分词器(Standard Analyzer)
- fields:多字段支持,允许您使用不同的分析器和索引选项在同一字段上创建多个索引字段。
- index:字段建立索引,注意,index 属性的默认值是 true,因此所有字段都会被默认建立索引。但对于某些情况,例如只需根据某个字段进行简单过滤,可以手动将 index 属性置为 false 来禁用索引。
- doc_values:是存储数据的方式之一,它将值序列化为一组高度压缩的列格式,以便于 CPU 进行快速操作。在默认情况下,每个被建立索引的字段都会自动创建一个 doc_values 字段。对于可以排序或聚合查询的字段,需要手动开启 doc_values,否则在排序或聚合操作时,默认使用 fielddata,会消耗大量的内存和 CPU 资源。
- fielddata:指定是否需要编制词条列表以及是否需要缓存词条列表以支持分析和聚合功能。
- format:用于日期字段的指定格式、数字类型的形态及 IP 地址解析器格式。
- copy_to:定义一个新字段,将多个字段值复制到新字段中,以便在查询时将值视为单个字段进行搜索,避免了使用bool查询的 overhead。
3.9 新增mapping
curl --location --request PUT 'http://foody.es.toc.test.sz.shop.io:31625/foody_test_th_filter_option_index_v1/_mapping'
--header 'Content-Type: application/json'
--data-raw '{
"properties":{
"id":{
"type":"long"
},
"name":{
"type":"text",
"analyzer":"simple",
"norms":false
},
"description":{
"type":"keyword",
"index":false,
"doc_values":false,
"norms":false
},
"status":{
"type":"byte",
"doc_values":false
},
"effective_time":{
"type":"long"
},
"expire_time":{
"type":"long"
},
"creator":{
"type":"keyword",
"doc_values":false,
"norms":false
},
"create_time":{
"type":"long"
},
"update_time":{
"type":"long",
"index":false,
"doc_values":false
},
"location_group_ids":{
"type":"keyword",
"doc_values":false,
"norms":false
}
}
}'
3.10 搜索所有的document
curl -XGET 'http://foody.es.toc.test.sz.shop.io:31625/foody_test_id_buyer_content_index_v1/_search'
curl -XPOST 'http://foody.es.toc.test.sz.shop.io:31625/foody_test_id_buyer_content_index_v1/_search'
结果
{
"took":37, //耗费时间,单位毫秒
"timed_out":false,//查询是否超时,可以自定义查询超时时间timeout=10ms
"_shards":{
"total":1, //参与分片的总数
"successful":1,
"skipped":0,
"failed":0
},
"hits":{
"total":{
"value":4412,
"relation":"eq"
},
"max_score":1,
"hits":[
{
"_index":"foody_test_id_buyer_content_index_v1",
"_type":"_doc",
"_id":"10036",
"_score":1,
"_source":{
"id":10036,
"position":6,
"type":6,
"name":"21",
"title":"",
"description":"",
"priority":1,
"image":"8e17242b7f76498367ec24c32a342a9b030b010000002c80000000000205001f",
"link":"https://test.shop.co.id/universal-link/now-food/storelisting/15728",
"store_ids":"",
"status":2,
"cities":null,
"effective_time":1649692800000,
"expire_time":1688118576000,
"time_ranges":"",
"creator":"mingqin.zhou@shop.com",
"create_time":1649924438817,
"update_time":1655808598444,
"location_group_ids":[
"291"
],
"working_group":null,
"listing_type":1
}
},
{
"_index":"foody_test_id_buyer_content_index_v1",
"_type":"_doc",
"_id":"100030",
"_score":1,
"_source":{
"id":100030,
"position":2,
"type":2,
"name":"BannerFlashSale",
"title":"",
"description":"",
"priority":1,
"image":"f4d2a7c0ff48209f884ece3be4c53db4030b01000001350200000000020500c1",
"link":"https://test.shop.co.id/universal-link/now-food/food-flash-sale?timeslotId=1033844441212928aab",
"store_ids":"",
"status":2,
"cities":null,
"effective_time":1653411600000,
"expire_time":1688131642000,
"time_ranges":"",
"creator":"yanghe.guo@shop.com",
"create_time":1653470101653,
"update_time":1654867663499,
"location_group_ids":[
"20"
],
"working_group":null,
"listing_type":1
}
}
}
]
}
}
3.11 查看某个document
curl -XGET 'http://foody.es.toc.test.sz.shop.io:31625/foody_test_id_buyer_content_index_v1/_doc/100132?pretty'
结果
{
"_index":"foody_test_id_buyer_content_index_v1",
"_type":"_doc",
"_id":"100132",
"_version":4,
"_seq_no":58019,
"_primary_term":9,
"found":true,
"_source":{
"id":100132,
"position":6,
"type":6,
"name":"test new33=32",
"title":"",
"description":"",
"priority":1,
"image":"8e17242b7f76498367ec24c32a342a9b030b010000002c80000000000205001f",
"link":"https://test.shop.co.id/universal-link/now-food/food-flash-sale?timeslotId=1033844441212928aab",
"store_ids":"",
"status":2,
"cities":null,
"effective_time":1655740800000,
"expire_time":1688115549000,
"time_ranges":"",
"creator":"shanshan.duan@shop.com",
"create_time":1655808227612,
"update_time":1655808227612,
"location_group_ids":[
"303"
],
"working_group":null,
"listing_type":1
}
}
3.12 查看所有节点信息
curl -XGET 'http://foody.es.toc.test.sz.shop.io:31625/_cat/nodes?pretty=true'
结果
ip 节点传输通道TCP端口 节点HTTP通道端口号 节点与集群通信传输层通道端口号 name
10.129.100.200 43 100 11 4.54 5.11 5.47 dim * node-01
10.129.97.143 43 70 4 0.36 0.42 0.69 dim - new-node-06
10.129.109.171 55 99 15 9.97 11.13 10.81 dim - new-node-10
10.129.100.233 66 98 22 15.27 16.98 16.98 dim - node-03
10.129.100.201 45 93 13 15.78 13.57 14.13 dim - node-02
10.129.109.133 54 99 11 9.99 9.56 9.66 dim - new-node-09
10.129.97.80 46 80 0 0.57 0.70 0.64 dim - new-node-05
10.129.97.79 38 95 1 2.73 1.54 1.16 dim - new-node-04
3.13 获取集群健康信息
curl -XGET 'http://foody.es.toc.test.sz.shop.io:31625/_cat/health?pretty=true'
结果
{
"cluster_name" : "es_toc_foody_test_sg2",
"status" : "green",
"timed_out" : false,
"number_of_nodes" : 8,
"number_of_data_nodes" : 8,
"active_primary_shards" : 2688,
"active_shards" : 5484,
"relocating_shards" : 0,
"initializing_shards" : 0,
"unassigned_shards" : 0,
"delayed_unassigned_shards" : 0,
"number_of_pending_tasks" : 0,
"number_of_in_flight_fetch" : 0,
"task_max_waiting_in_queue_millis" : 0,
"active_shards_percent_as_number" : 100.0
}
3.14 查看集群状态
curl -XGET 'http://foody.es.toc.test.sz.shop.io:31625/_cluster/state?pretty=true'
结果
{
"state" : "STARTED",
"primary" : true,
"node" : "0XvaTaczRyGnK83MiU2g4A",
"relocating_node" : null,
"shard" : 1,
"index" : "foody_migration_vn_driver_wallet_order_index_v1_staging",
"allocation_id" : {
"id" : "tx7KDeObRFKFt2cKxG9Kjg"
}
},
{
"state" : "STARTED",
"primary" : true,
"node" : "0XvaTaczRyGnK83MiU2g4A",
"relocating_node" : null,
"shard" : 4,
"index" : "spx_test_local_return_index_v1",
"allocation_id" : {
"id" : "UVHinETvRxWz01o_bsIRng"
}
},
3.15 查看集群的统计信息
curl -XGET 'http://foody.es.toc.test.sz.shop.io:31625/_cluster/stats?pretty=true'
结果
{
"_nodes" : {
"total" : 8,
"successful" : 8,
"failed" : 0
},
"cluster_name" : "es_toc_foody_test_sg2",
"cluster_uuid" : "fzJChrVNROy1p_kCnLOK5w",
"timestamp" : 1687789389538,
"status" : "green",
"indices" : {
"count" : 2177,
"shards" : {
"total" : 5484,
"primaries" : 2688,
"replication" : 1.0401785714285714,
"index" : {
"shards" : {
"min" : 2,
"max" : 20,
"avg" : 2.5190629306384933
},
"primaries" : {
"min" : 1,
"max" : 10,
"avg" : 1.234726688102894
},
"replication" : {
"min" : 1.0,
"max" : 2.0,
"avg" : 1.0146991272393202
}
}
},
"docs" : {
"count" : 217876728,
"deleted" : 13951480
},
"store" : {
"size_in_bytes" : 165242915579
},
"fielddata" : {
"memory_size_in_bytes" : 2640,
"evictions" : 0
},
"query_cache" : {
"memory_size_in_bytes" : 548616285,
"total_count" : 12976266974,
"hit_count" : 542463781,
"miss_count" : 12433803193,
"cache_size" : 59358,
"cache_count" : 28385811,
"evictions" : 28326453
},
"completion" : {
"size_in_bytes" : 0
},
"segments" : {
"count" : 17707,
"memory_in_bytes" : 295059397,
"terms_memory_in_bytes" : 154021197,
"stored_fields_memory_in_bytes" : 38884696,
"term_vectors_memory_in_bytes" : 0,
"norms_memory_in_bytes" : 3113280,
"points_memory_in_bytes" : 69893926,
"doc_values_memory_in_bytes" : 29146298,
"index_writer_memory_in_bytes" : 337259756,
"version_map_memory_in_bytes" : 21290864,
"fixed_bit_set_memory_in_bytes" : 33017008,
"max_unsafe_auto_id_timestamp" : 1687737602329,
"file_sizes" : { }
}
},
"nodes" : {
"count" : {
"total" : 8,
"coordinating_only" : 0,
"data" : 8,
"ingest" : 8,
"master" : 8,
"ml" : 0,
"voting_only" : 0
},
"versions" : [
"7.4.2"
],
"os" : {
"available_processors" : 416,
"allocated_processors" : 336,
"names" : [
{
"name" : "Linux",
"count" : 8
}
],
"pretty_names" : [
{
"pretty_name" : "Ubuntu 16.04.6 LTS",
"count" : 8
}
],
"mem" : {
"total_in_bytes" : 2561664008192,
"free_in_bytes" : 120132288512,
"used_in_bytes" : 2441531719680,
"free_percent" : 5,
"used_percent" : 95
}
},
"process" : {
"cpu" : {
"percent" : 1
},
"open_file_descriptors" : {
"min" : 4934,
"max" : 5695,
"avg" : 5380
}
},
"jvm" : {
"max_uptime_in_millis" : 11917418820,
"versions" : [
{
"version" : "12.0.2",
"vm_name" : "OpenJDK 64-Bit Server VM",
"vm_version" : "12.0.2+10",
"vm_vendor" : "Oracle Corporation",
"bundled_jdk" : false,
"using_bundled_jdk" : null,
"count" : 8
}
],
"mem" : {
"heap_used_in_bytes" : 31309736736,
"heap_max_in_bytes" : 62277025792
},
"threads" : 3027
},
"fs" : {
"total_in_bytes" : 24908083396608,
"free_in_bytes" : 19282914426880,
"available_in_bytes" : 18269939757056
},
"plugins" : [ ],
"network_types" : {
"transport_types" : {
"security4" : 8
},
"http_types" : {
"security4" : 8
}
},
"discovery_types" : {
"zen" : 8
},
"packaging_types" : [
{
"flavor" : "default",
"type" : "tar",
"count" : 8
}
]
}
}
注意:PUT和XPUT区别,实际上是类似的,在一些特定情况下,XPUT比PUT更灵活,支持更高级的操作,例如:
- 指定其他参数进行额外的操作,例如参数 pipeline 用于在写入文档之前对文档执行指定的操作。
- 在文档中使用更复杂的字段类型,例如 nested 和 geo_point 等字段类型。
- 可以在一步操作中创建索引、映射和文档,而不需要先创建索引和映射,然后再写入文档。
3.16 Elasticsearch 提供的JSON查询语言
3.16.1 match查询
用于全文搜索,并且支持各种不同的搜索选项,例如模糊搜索、匹配短语、搜索范围等。“title”:exampla 也会返回
{
"query":{
"match":{
"title":"example"
}
}
}
3.16.2 match_phrase查询
精确匹配一系列单词或者_短语_,下面例子仅匹配同时包含 “rock” 和 “climbing”
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
}
}
3.16.3 match_all查询
用于匹配所有文档的查询语句,该查询语句不接受任何参数
{
"query": {
"match_all": {}
}
}
3.16.4 term查询
用于精确匹配字段中的值,不会将查询字符串分析成单词
{
"query":{
"term":{
"author":"james"
}
}
}
3.16.5 range查询
用于按范围查询数字、日期或者字符串值
{
"query":{
"range":{
"timestamp":{
"gte":"2021-01-01",
"lt":"2021-02-01"
}
}
}
}
3.16.6 bool查询
用户组合多个查询语言,可以使用must、should等逻辑关系对它们进行组合
{
"query":{
"bool": {
"must": [
{ "match": { "title": "example" } },
{ "range": { "timestamp": { "gte": "2021-01-01" } } }
],
"filter": [
{ "term": { "status": "published" }},
{ "range": { "publish_date": { "gte": "2015-01-01" }}}
]
}
}
}
3.16.7 match_phrase_prefix查询
用于匹配一个短语的前缀,并返回所有以该前缀的短语。
{
"query":{
"match_phrase_prefix":{
"title":"exam"
}
}
}
举个例子
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
}
}
}
解释一下:
- must 子句表示必须满足的条件,需要精确地匹配 user 字段为 kimchy 的文档。
- filter 子句表示需要过滤的条件,需要精确地匹配 tag 字段为 tech 的文档。与 must 不同的是,filter 不影响结果的相关性得分 (relevance score)。
- must_not 子句表示必须不满足的条件,需要过滤掉其中 age 字段在 10 到 20 之间的文档。
- should 子句表示可选的条件,需要匹配其中至少一个条件。这里需要匹配 tag 字段为 wow 或者为 elasticsearch 的文档。
- minimum_should_match 参数表示至少需要满足的 should 子句数量,这里设置为 1,表示至少需要匹配一个 should 条件。
- boost 参数表示提高或降低查询某个条件的相关性得分,默认为 1.0。
总体来说,以上查询表示需要匹配 user 为 kimchy 且 tag 为 tech 的文档,并且在这些匹配的文档中,不能存在 age 在 10 到 20 之间的文档。最后,在还未过滤的文档中,需要匹配其中至少一个 tag 为 wow 或者 elasticsearch 的文档。这样形成的结果集会按照相关性得分进行排序,相关性得分越高的文档排在前面。
四、延伸阅读
ElasticSearch官方文档:https://www.elastic.co/guide/en/elasticsearch/guide/current/getting-started.html
Elasticsearch GitHub:
https://github.com/elastic/elasticsearch
在 Golang 中,有很多开源的 Elasticsearch 框架或工具可供选择。以下是一些常用的框架或工具:
- Elasticsearch 的官方 Elasticsearch Go 客户端:https://github.com/elastic/go-elasticsearch
- Elasticsearch 官方推荐的高级客户端 Elasticsearch Go SDK:https://github.com/elastic/go-elasticsearch
- 封装 Elasticsearch API,提供高性能查询和聚合操作的的 beego 工具库:https://beego.me/docs/mvc/model/elasticsearch.md
- Elasticsearch 映射工具和查询构造器 Goicano:https://github.com/mkmanu/goicano
- 轻量级 Elasticsearch 客户端 Elastigo:https://github.com/mattbaird/elastigo
- 用于创建灵活的 Elasticsearch 应用程序的 Olivere Elastic 客户端:https://github.com/olivere/elastic 目前代码中使用这种