Go操作Elasticsearch总结
Go操作Elasticsearch总结
安装
参见:CentOS 7 RPM安装 Elasticsearch 7.14.1和常用插件
官方入门例子
《Elasticsearch:权威指南》“适应新环境” 通过一个例子,介绍了ES的核心概念。
我们受雇于 Megacorp 公司,作为 HR 部门新的 “热爱无人机” (“We love our drones!”)激励项目的一部分,我们的任务是为此创建一个员工目录。该目录应当能培养员工认同感及支持实时、高效、动态协作,因此有一些业务需求:
- 支持包含多值标签、数值、以及全文本的数据
- 检索任一员工的完整信息
- 允许结构化搜索,比如查询 30 岁以上的员工
- 允许简单的全文搜索以及较复杂的短语搜索
- 支持在匹配文档内容中高亮显示搜索片段
- 支持基于数据创建和管理分析仪表盘
ES-Head使用
Structured Query:
Any Request页面可以自己写各种查询语句(看官方API examples时直接贴过来调试):
Kibana使用
最常用的是:Management / 开发工具
Elasticsearch API总结
插入数据(自动创建索引)
- website:index,索引名称
- blog:documentType,索引类型,目前统一设置为_doc,后续ES高版本好像放弃了。
- 123:id,索引ID。
一般不指定,通过ES自动生成
,插入速度更快。
POST /website/blog/123
{"title": "My first blog entry","text": "Just trying this out...","date": "2014/01/01"
}
创建映射
如果不显示创建索引,则一些字段聚合查询的时候会报错,因为没有指定字段类型。聚合查询操作只支持keyword。
增删改查映射可以参考:
- 《ES权威指南2.x》
- 7.x最新的API
创建一个显式映射
的例子:
PUT /my-index-000001
{"mappings": {"properties": {"age": { "type": "integer" }, "email": { "type": "keyword" }, "name": { "type": "text" } }}
}
支持的数据类型可以参考:Field data types
- Keywords: The keyword family, including keyword, constant_keyword, and wildcard.
- Numbers: Numeric types, such as long and double, used to express amounts.
- Dates: Date types, including date and date_nanos.
- text: Analyzed, unstructured text.
- alias: Defines an alias for an existing field.
此时,就可以对email聚合统计(为什么?因为text会被分词,keywords不会分词?),或者去重了。
创建索引
当然,可以直接在创建索引的时候指定。那为何还要单独创建映射?因为es不是列式存储的,不像数据库需要提前创建表,指定有多少个字段(列),es是可以动态增加字段(列)的。
具体参考:https://www.elastic.co/guide/cn/elasticsearch/guide/current/_creating_an_index.html
PUT /my_index
{"settings": { ... any settings ... },"mappings": {"type_one": { ... any mappings ... },"type_two": { ... any mappings ... },...}
}
删除索引
具体参考:https://www.elastic.co/guide/cn/elasticsearch/guide/current/_deleting_an_index.html
DELETE /my_index
查询API
具体参见:https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html
GET /my-index-000001/_search?from=40&size=20
{ "query": { "term": { "user.id": "kimchy" } }
}
{"took": 5,"timed_out": false,"_shards": {"total": 1,"successful": 1,"skipped": 0,"failed": 0},"hits": {"total": {"value": 20,"relation": "eq"},"max_score": 1.3862942,"hits": [{"_index": "my-index-000001","_type" : "_doc","_id": "0","_score": 1.3862942,"_source": {"@timestamp": "2099-11-15T14:12:12","http": {"request": {"method": "get"},"response": {"status_code": 200,"bytes": 1070000},"version": "1.1"},"source": {"ip": "127.0.0.1"},"message": "GET /search HTTP/1.1 200 1070000","user": {"id": "kimchy"}}},...]}
}
聚合查询API
具体API参考:权威指南2.x:聚合、Aggregations
GET /my-index-000001/_search
{"aggs": {"my-agg-name": {"terms": {"field": "my-field"}}}
}
GO操作Elasticsearch
先在pkg.go.dev
搜索一下:
选第一个,进去后点击Expand展开,就有更详细的入门例子。
PS:v7是针对elasticsearch 7.x版本,使用前要确认自己的es版本。7.x和6.x有些许出入,如果用了7.x开发,降级到6.x难度也不算大。
Import"github.com/elastic/go-elasticsearch/v6""github.com/elastic/go-elasticsearch/v6/esapi""github.com/elastic/go-elasticsearch/v6/esutil"
Example
cfg := elasticsearch.Config{Addresses: []string{"http://localhost:9200","http://localhost:9201",},Username: "foo",Password: "bar",Transport: &http.Transport{MaxIdleConnsPerHost: 10,ResponseHeaderTimeout: time.Second,DialContext: (&net.Dialer{Timeout: time.Second}).DialContext,TLSClientConfig: &tls.Config{MinVersion: tls.VersionTLS11,},},
}es := elasticsearch.NewClient(cfg)// 测试
_, err = client.Ping()
if err != nil {return err
} else {logger.Info("success connect to elasticsearch:", conf.Addresses)
}// 打印es版本信息
res, err := es.Info()
if err != nil {log.Fatalf("Error getting response: %s", err)
}
log.Println(res)
查询操作
方式一:使用go函数
// go 构造json便捷写法
type H map[string]interface{}
queryMap := H{"query": H{"term": H{"user.id": "kimchy",},},
}data, err := json.Marshal(queryMap)
if err != nil {return
}// 执行搜索操作
res, err := es.client.Search(es.client.Search.WithContext(context.Background()),es.client.Search.WithIndex(es.toIndex),es.client.Search.WithDocumentType(es.toType),es.client.Search.WithBody(strings.NewReader(query)),es.client.Search.WithPretty(),
)defer res.Body.Close()
if err != nil {return
}// 需要再次判断
if res.IsError() {var e map[string]interface{}if err := json.NewDecoder(res.Body).Decode(&e); err != nil {logger.Sugar.Fatalf("Error parsing the response body: %s", err)return nil, err} else {// Print the response status and error information.logger.Sugar.Errorf("[%s] %s: %s",res.Status(),e["error"].(map[string]interface{})["type"],e["error"].(map[string]interface{})["reason"],)}
}// 读取所有
b, err := ioutil.ReadAll(res.Body)
if err != nil {return nil, err
}
方式二:直接使用http请求
这里以创建映射举例,search同理:
// CreateMapping 创建映射
func (e *Elastic) CreateMapping(index, jsonData string) error {url := fmt.Sprintf("http://10.0.56.153:9200/steel-index")req, _ := http.NewRequest("PUT", url, strings.NewReader(jsonData))req.Header.Add("Content-Type", "application/json")res, err := e.httpClient.Do(req)if err != nil {return err}defer res.Body.Close()body, _ := ioutil.ReadAll(res.Body)logger.Info("success create mapping index: ", index, ",res:", string(body))return nil
}
插入
func (e *Elastic) Post(jsonData string) error {req := esapi.IndexRequest{Index: e.toIndex,DocumentType: e.toType,Body: strings.NewReader(jsonData),Timeout: time.Second * 10,}res, err := req.Do(context.Background(), e.client)if err != nil {return err}defer res.Body.Close()if !res.IsError() {// Deserialize the response into a map.var r map[string]interface{}if err := json.NewDecoder(res.Body).Decode(&r); err != nil {logger.Sugar.Warnf("Error parsing the response body: %s", err)} else {// Print the response status and indexed document version.logger.Sugar.Infof("[%s] %s; version=%d", res.Status(), r["result"], int(r["_version"].(float64)))}} else {logger.Sugar.Warn("Error post elastic,statsCode:", res.StatusCode, ",string:", res.String())}return nil
}
批量插入(bulk)
具体可以参考官方的这篇博客:The Go client for Elasticsearch: Working with data
// AddBulk 批量添加进ES
// see more: https://www.elastic.co/cn/blog/the-go-client-for-elasticsearch-working-with-data
func (e *Elastic) AddBulk(index, docType string, numWorkers, flushBytes int, jsonData []string) error {bulkIndexer, err := esutil.NewBulkIndexer(esutil.BulkIndexerConfig{Index: index, // The default index nameDocumentType: docType,Client: e.client, // The Elasticsearch clientNumWorkers: numWorkers, // The number of worker goroutinesFlushBytes: flushBytes, // The flush threshold in bytesFlushInterval: 30 * time.Second, // The periodic flush interval})if err != nil {return err}var countSuccessful uint64 = 0// 组合,具体参考ES Bulk API:https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-bulk.html#bulk-api-request-bodyfor _, str := range jsonData {err := bulkIndexer.Add(context.Background(), esutil.BulkIndexerItem{// Action field configures the operation to perform (index, create, delete, update)Action: "index",// DocumentID is the (optional) document ID// DocumentID: strconv.Itoa(a.ID),// Body is an `io.Reader` with the payloadBody: strings.NewReader(str),// OnSuccess is called for each successful operationOnSuccess: func(ctx context.Context, item esutil.BulkIndexerItem, res esutil.BulkIndexerResponseItem) {atomic.AddUint64(&countSuccessful, 1)},// OnFailure is called for each failed operationOnFailure: func(ctx context.Context, item esutil.BulkIndexerItem, res esutil.BulkIndexerResponseItem, err error) {if err != nil {logger.Infof("ERROR: %s", err)} else {logger.Infof("ERROR: %s: %s", res.Error.Type, res.Error.Reason)}},})if err != nil {return err}}start := time.Now()// Close waits until all added items are flushed and closes the indexer.if err := bulkIndexer.Close(context.Background()); err != nil {return err} else {// 统计时间biStats := bulkIndexer.Stats()dur := time.Since(start)if biStats.NumFailed > 0 {logger.Warnf("Indexed [%s] documents with [%s] errors in %s (%s docs/sec)",Comma(int64(biStats.NumFlushed)),Comma(int64(biStats.NumFailed)),dur.Truncate(time.Millisecond),Comma(int64(1000.0/float64(dur/time.Millisecond)*float64(biStats.NumFlushed))),)} else {logger.Infof("Successfully indexed [%s] documents in %s (%s docs/sec)",Comma(int64(biStats.NumFlushed)),dur.Truncate(time.Millisecond),Comma(int64(1000.0/float64(dur/time.Millisecond)*float64(biStats.NumFlushed))),)}}return nil
}
删除
// 删除索引
func (e *Elastic) DeleteIndex(index string) error {url := fmt.Sprintf("http://%s/%s", config.DefaultConfig.ES.Addr, index)req, _ := http.NewRequest("DELETE", url, nil)res, err := e.httpClient.Do(req)if err != nil {return err}defer res.Body.Close()body, _ := ioutil.ReadAll(res.Body)logger.Info("success delete index: ", index, ",res:", string(body))return nil
}
关于作者
推荐下自己的开源IM,纯Golang编写:
CoffeeChat:https://github.com/xmcy0011/CoffeeChat
opensource im with server(go) and client(flutter+swift)
参考了TeamTalk、瓜子IM等知名项目,包含服务端(go)和客户端(flutter+swift),单聊和机器人(小微、图灵、思知)聊天功能已完成,目前正在研发群聊功能,欢迎对golang感兴趣的小伙伴Star加关注。
Go操作Elasticsearch总结相关推荐
- SpringBoot 操作elasticsearch
SpringBoot 操作elasticsearch 版本环境 jdk1.8 elasticsearch 7.6.1 maven <dependency><groupId>or ...
- SpringBoot 操作 ElasticSearch 详解(万字长文)
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:超级小豆丁 http://www.mydlq.club/ar ...
- java操作elasticsearch实现query String
1.CommonTersQuery: 指定字段进行模糊查询 //commonTermsQuery @Test public void test35() throws UnknownHostExcept ...
- 万字长文:详解 Spring Boot 中操作 ElasticSearch
点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | 超级小豆丁 来源 | http://www.m ...
- 基于Python操作ElasticSearch
基于Python操作ElasticSearch 原文:https://blog.csdn.net/hanyuyang19940104/article/details/81168763?utm_sour ...
- Python操作ElasticSearch
Python操作ElasticSearch pip install elasticsearch 单一操作 插入 create:必须指定待查询的idnex.type.id和查询体body:缺一不可,否 ...
- elasticsearch 客户端工具_万字长文:详解 Spring Boot 中操作 ElasticSearch
点击上方"小强的进阶之路",选择"星标"公众号 优质文章,及时送达 预计阅读时间: 15分钟 一.ElasticSearch 简介 1.简介 ElasticSe ...
- python elasticsearch模块_Python 操作 ElasticSearch
Python操作ElasticSearch Python批量向ElasticSearch插入数据 Python 2的多进程不能序列化类方法, 所以改为函数的形式. 直接上代码: #!/usr/bin/ ...
- ElasticSearch-.net平台下c#操作ElasticSearch详解
ElasticSearch系列学习 ElasticSearch第一步-环境配置 ElasticSearch第二步-CRUD之Sense ElasticSearch第三步-中文分词 ElasticSea ...
- 使用Sense操作ElasticSearch CRUD
安装完成之后,我们该开始学习关于ElasticSearch最基本的CURD操作了. google浏览器安装需要翻墙. ElasticSearch作为一个基于Lucene的搜索服务器.它提供了一个分布式 ...
最新文章
- JS改变input的value值不触发onchange事件解决方案 (转)
- typedef和define一些问题
- boost::distance用法的测试程序
- getparent_Java文件类字符串getParent()方法(带示例)
- macos必做的设置_如何在MacOS上设置PHP,CaddyServer和Kirby —以及为什么要这样做
- lr分析器的设计与实现实验_GBDT+LR:Practical Lessons from Predicting Clicks on Ads
- mysql的bht_BHT
- ubuntu linux软件,Linux新系统必装软件(Ubuntu及类似系统)
- 关键路径过程详解、算法及其实现
- 用excel打开txt文件
- 常用制作钓鱼网站的工具
- A Question of Ingestion Gym - 101673G
- 建网站如何选择空间?
- 凯撒密码:设想在某些情况下给朋友传递字条信息,但又不希望传递中途被第三方看懂这些信息,因此需要对字条信息进行加密处理
- 微信小程序实现图片文字识别提取
- 【linux驱动】USB子系统分析
- 2022年自考专业(工商企业管理)企业管理概论练习题
- 下雨天的十月末还不冷
- 条条就要离开上海去南通工作了
- 分享4张炫酷农业大屏模板,Smartbi教你“智慧”种田
热门文章
- layui 的简单使用
- 解决:无法打开文件“GCBase_MD_VC120_v3_0_Basler_pylon_v5_0.lib”
- js模块化:详解与面试
- 细说linux挂载——mount,及其他
- 文件服务器怎么关机,服务器怎么关机和重启
- Markdown编辑器和富文本编辑器的区别
- R语言对多个数据框的相同列进行操作
- apk反编译工具及使用步骤(详解)
- 以水稻为例教你如何使用BSA方法进行遗传定位(下篇)
- java识别节奏,Flutter AudioPlayers 或节拍器滞后