网上做论文的网站有哪些,企业管理培训公司排名,app软件制作多少钱,太湖网站建设推荐秒搜科技文章目录 一、环境准备1、 docker安装ES2、启动容器3、图像化客户端工具ElasticSearch-Head 二、Go ES连接与认证1、 连接ES2、配置ES认证 三、索引的增删改查四、文档的增删改创建单个文档根据文档id删除文档批量删除文档批量创建文档 五、文档查询列表查询精确匹配模糊匹配嵌… 文章目录 一、环境准备1、 docker安装ES2、启动容器3、图像化客户端工具ElasticSearch-Head 二、Go ES连接与认证1、 连接ES2、配置ES认证 三、索引的增删改查四、文档的增删改创建单个文档根据文档id删除文档批量删除文档批量创建文档 五、文档查询列表查询精确匹配模糊匹配嵌套字段的搜索 六、 更新文档 代码地址
https://gitee.com/lymgoforIT/golang-trick/tree/master/34-go-es 一、环境准备
1、 docker安装ES
首先需要先安装docker这个网上教程很多这里就默认docker已经安装好了。当然如果不想用docker的话也可以和redis、kafka等组件一样下载后加压、配置环境变量便可以开始使用了。
拉取elasticsearch的镜像
docker pull elasticsearch:7.12.0创建docker容器挂载的目录
之所以在容器启动的时候要配置挂载的宿主机目录是因为想要在宿主机本机上记录下来当前ES容器的配置信息数据以及插件等这样即使到时候我们把容器删了重新用镜像生成容器时只要挂载的还是这三个目录那么即使镜像变了端口变了但是启动的容器和之前的会是一样的。
PS挂载指是是宿主机本机的目录映射到容器中的某个目录一方改动另一方会相应的改动通过容器启动时 -v 选项配置。
主要是三个目录config 、data 、plugins其实我们如果是自己安装ES而不是通过docker安装的话也是可以看到这三个目录的。 既然我们本次是用docker演示的那就手动创建一下这三个目录吧如下放到了自己建的docker-es目录下 然后在config目录下建立配置文件elasticsearch.yml并写入内容 http.host: 0.0.0.0表示监听本机上的所有IP地址, 也就是接收本机所有网卡发到本进程端口的请求
如果是linux的话通过命令就可以完成上述步骤了当然目录名字就稍微换了毕竟linux没有盘符的概念
# linux的命令
mkdir -p /opt/es/config mkdir -p /opt/es/data mkdir -p /opt/es/pluginschmod 777 /opt/es/dataecho http.host: 0.0.0.0 /opt/es/config/elasticsearch.yml2、启动容器
linux docker run --name es -p 9200:9200 -p 9300:9300 -e discovery.typesingle-node -e ES_JAVA_OPTS-Xms84m -Xmx512m -v /opt/es/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /opt/es/data:/usr/share/elasticsearch/data -v /opt/es/plugins:/usr/share/elasticsearch/plugins -d elasticsearch:7.12.0windows docker run --name es -p 9200:9200 -p 9300:9300 -e discovery.typesingle-node -e ES_JAVA_OPTS-Xms84m -Xmx512m -v D:\\GoDevKit\\ElasticSearch\\docker-es\\config\\elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v D:\\GoDevKit\\ElasticSearch\\docker-es\\data:/usr/share/elasticsearch/data -v D:\\GoDevKit\\ElasticSearch\\docker-es\\plugins:/usr/share/elasticsearch/plugins -d elasticsearch:7.12.0
解释
docker run 运行容器的命令--name:启动后容器的名字 -p:端口映射表示访问宿主机的9200端口会映射访问到容器的9200端口9200是外部访问es的restful端口9300是es集群内部节点之间通信的端口。-e ES_JAVA_OPTS-Xms84m -Xmx512m: es是Java写的这里是设置Java虚拟机相关参数-v:目录挂载映射这里也可以看到es容器是自带了那三个目录的就像我们自己安装es一样只是现在我们想将宿主机的三个目录与之映射这样即使删除了容器之前新建的容器只要还是挂载的宿主机这三个目录那就还是会和原来的容器一样的。-d:后台运行最后的参数时镜像名字
启动成功
通过docker desktop可以看到容器正在运行中了 访问本机的9200端口 并且可以看到我们创建的data空目录中也就有一些数据了 3、图像化客户端工具ElasticSearch-Head
ElasticSearch-Head的安装和使用可以参考https://www.cnblogs.com/xuwenjin/p/8792919.html
1、elasticsearch-head是一个基于node.js的前端工程所以需要先安装node.js下载地址https://nodejs.org/en/download下载完成后基本就是无脑式下一步即可安装完成后使用node -v查看版本判断是否安装成功。 2、安装grunt为全局命令grunt是基于node.js的项目构建工具
npm install -g grunt-cli将grunt需要的一些jar包也安装上需要联网下载可能需要一点时间
npm instll3、下载elasticsearch-head配置包下载地址https://github.com/mobz/elasticsearch-head
下载后进入到该目录中打开cmd输入npm run start 打开浏览器连接绿色表示连接成功了事实上第一次操作是连接不上的因为9100去连接9200端口属于跨域了是会被拒绝了所以需要在elasticsearch.yml配置文件中加上允许跨域连接的配置
http.cors.enabled: true
http.cors.allow-origin: *然后通过docker desktop 重启重启容器就可以看到连接成功啦 二、Go ES连接与认证
安装依赖包
go get github.com/olivere/elastic/v71、 连接ES
对于连接操作我们一般都是会定义一个包级别的变量然后提供一个显示的Init方法然后在main方法中初始化如下
es_connect.go
package coreimport (fmtgithub.com/olivere/elastic/v7
)var EsClient *elastic.Clientfunc InitEsConn() {client, err : elastic.NewClient(elastic.SetURL(http://127.0.0.1:9200), // ES服务器地址// 我们的ES是通过docker启动的所以会有docker为其分配的IP地址但是我们想用本机的然后通过端口映射访问到docker中的所以这里设置false表示跳过IP检查elastic.SetSniff(false),elastic.SetBasicAuth(, ),)if err ! nil {panic(any(err))}EsClient clientfmt.Println(EsClient)
}
main.go
package mainimport golang-trick/34-go-es/corefunc main() {core.InitEsConn()
}
运行后可以看到连接成功 2、配置ES认证
不需要认证的情况
服务器自己使用92009300端口不对外开放本身跑在127.0.0.1上
需要认证的情况
ES需要对外提供服务的我们总不能让外部也能随意通过ip:端口的方式随意的访问到我们的ES数据所以需要配置认证
配置认证的方式参考https://blog.csdn.net/qq_38669698/article/details/130529829
启用认证由于我们配置了目录映射所以改宿主机的elasticsearch.yml文件即可添加如下内容
#添加如下内容
#http.cors.allow-headers: Authorization #这个配置改为下面的
http.cors.allow-headers: Authorization,X-Requested-With,Content-Length,Content-Type
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true2.保存后重启ES
docker restart es设置用户密码
a. 上一步重启ES容器后进入容器
docker exec -it es /bin/bashb. 进入容器后执行以下命令
./bin/elasticsearch-setup-passwords interactive出现Initiating the setup of passwords for reserved users elastic,apm_system,kibana,logstash_system,beats_system,remote_monitoring_user.
You will be prompted to enter passwords as the process progresses.
Please confirm that you would like to continue [y/N]上边英文大概的意思是你如果确定开启密码的话需要设置以下六种账户的密码建议设置成一样的
Please confirm that you would like to continue [y/N]yEnter password for [elastic]:
Reenter password for [elastic]:
Enter password for [apm_system]:
Reenter password for [apm_system]:
Enter password for [kibana]:
Reenter password for [kibana]:
Enter password for [logstash_system]:
Reenter password for [logstash_system]:
Enter password for [beats_system]:Reenter password for [beats_system]:
Enter password for [remote_monitoring_user]:
Reenter password for [remote_monitoring_user]:
Changed password for user [apm_system]
Changed password for user [kibana]
Changed password for user [logstash_system]
Changed password for user [beats_system]
Changed password for user [remote_monitoring_user]
Changed password for user [elastic]c.完成以上的设置后需要再次重启ES容器
d. 验证
http://127.0.0.1:9200/可以看到再次访问就需要我们输入用户名和密码了用户名是固定的elastic密码则是我们自己设置的 现在执行我们开始的连接代码也会报错了因为没有给用户名和密码 此外使用ES-Head连接时也需要改为http://localhost:9100/?auth_userelasticauth_password123456即需要带上用户名和密码了 三、索引的增删改查 首先我们创建一个结构体User用于后续封装从ES中查询的出来的数据并设置一个mapping(定义索引下的字段约束其中properties表示的就是索引下文档的各字段
user.go 类似MySQL中的Model定义结构体表名等。这里就是ES的Model定义索引名和mapping等。
package modelimport timetype User struct {Id uint json:idUserName string json:user_nameNickName string json:nick_name//Age int json:ageCreateAt string json:create_atTitle string json:title
}func (u *User) Index() string{return user_index
}func (u *User) Mapping() string {return
{mappings: {properties: {nick_name: { type: text},user_name: { type: keyword // 完整匹配},age: { type: integer // 完整匹配},id: {type: integer},created_at:{type: date,null_value: null,format: [yyyy-MM-dd HH:mm:ss]}}}
}}
index.go :索引的创建、删除、判断索引是否已经存在
package indexsimport (contextfmtgolang-trick/34-go-es/coregolang-trick/34-go-es/model
)func CreateIndex(indexName string) error {// 索引不存在时我们才创建,否则请求创建已经存在的索引会报错的if ExistsIndex(indexName) {// 删除已经存在的索引然后新建索引err : DeleteIndex(indexName)if err ! nil {return err}}index, err : core.EsClient.CreateIndex(indexName). // 创建索引BodyString((model.User{}).Mapping()). // 指定索引的mapping类似mysql中的表各字段的一个类型和其他约束Do(context.Background()) // 执行if err ! nil {fmt.Println(err)return err}fmt.Println(fmt.Printf(创建了索引,索引%v, index))return nil
}func ExistsIndex(indexName string) bool {exists, _ : core.EsClient.IndexExists(indexName).Do(context.Background())return exists
}func DeleteIndex(indexName string) error {_, err : core.EsClient.DeleteIndex(indexName).Do(context.Background())fmt.Println(删除了索引)return err}运行
package mainimport (golang-trick/34-go-es/coregolang-trick/34-go-es/indexs
)func main() {core.InitEsConn()indexs.CreateIndex(user_index)
}
从ES-Head中可以看到索引和相关字段了 再次执行的话会按我们的代码定义的方式先删除原有的索引然后创建新的索引 四、文档的增删改
创建单个文档
package docsimport (contextfmtgolang-trick/34-go-es/coregolang-trick/34-go-es/modeltime
)func CreateDoc() {user : model.User{Id: 10,UserName: lym,NickName: 夜空中最亮的星,CreateAt: time.Now().Format(2006-01-02 15:03:04), // 需要按照mapping中的约束格式传否则报错Title: 学习创建索引,}indexResp, err : core.EsClient.Index(). // 表明是要对索引进行操作Index(user.Index()). // 指定要操作的索引BodyJson(user). // 文档的内容会将结构体给我们转为JSON字符串Do(context.Background()) // 执行if err ! nil {fmt.Println(err)return}fmt.Printf(%#v\n, indexResp)
}
运行
package mainimport (golang-trick/34-go-es/coregolang-trick/34-go-es/docs
)func main() {core.InitEsConn()// indexs.CreateIndex(user_index)docs.CreateDoc()
} 要注意的是这样查看显示的数据是不全的比如上面就没有显示title和create_at字段可以点击文档查看JSON样式的完整数据 如果是mapping里面没有的字段文档也是可以创建成功的并且会加上该字段如上面的title字段在mapping中就是没有的但是也保存到文档中成功了。
根据文档id删除文档
// 注意这里的id是文档id不是文档内容中的id字段
func DeleteDoc(id string) {deleteResp, err : core.EsClient.Delete(). // 获取一个DeleteService对象Index((model.User{}).Index()). // 指明索引Id(id).Refresh(true). // 删除后索引会过一会才刷新这里传true索引会立即刷新删除操作我们一般都传trueDo(context.Background())if err ! nil { // 如果文档不存在会报404错误fmt.Println(err)return}fmt.Printf(%#v\n, deleteResp)}执行
package mainimport (golang-trick/34-go-es/coregolang-trick/34-go-es/docs
)func main() {core.InitEsConn()// indexs.CreateIndex(user_index)//docs.CreateDoc()docs.DeleteDoc(d6ldWYwBwPESsKz-qasv)
} 批量删除文档
批量删除需要用到Bulk对象将要操作的文档放入Bulk中然后一次性提交给ES服务器执行 执行前我们又插入了两条数据用于测试
根据文档ID列表批量删除文档代码 // 注意这里的id是文档id不是文档内容中的id字段
// 传入文档id列表
func BatchDeleteDoc(ids []string) {bulkService : core.EsClient.Bulk(). // 获取BulkService对象Index((model.User{}).Index()). // 指明要操作的索引Refresh(true)for _, id : range ids {bulk : elastic.NewBulkDeleteRequest().Id(id)bulkService.Add(bulk)}bulkResp, err : bulkService.Do(context.Background())if err ! nil {fmt.Println(err)return}// 如果文档不存在不会有错误bulkResp.Succeeded()为空否则就是删除成功的数量fmt.Printf(%#v\n, bulkResp.Succeeded()) }
执行
package mainimport (golang-trick/34-go-es/coregolang-trick/34-go-es/docs
)func main() {core.InitEsConn()// indexs.CreateIndex(user_index)//docs.CreateDoc()//docs.DeleteDoc(d6ldWYwBwPESsKz-qasv)docs.BatchDeleteDoc([]string{eKmUWYwBwPESsKz-8qsp, eamVWYwBwPESsKz-DKve})
}
批量删除成功 批量创建文档
与批量删除类似只是添加到BulkService对象中的对象变为了BulkCreateRequest
func BatchCreateDoc() {userList : []model.User{{Id: 11,UserName: lym,NickName: 夜空中最亮的星,CreateAt: time.Now().Format(2006-01-02 15:04:05),},{Id: 12,UserName: lym,NickName: 夜空中最亮的星,CreateAt: time.Now().Format(2006-01-02 15:04:05),},}bulkService : core.EsClient.Bulk(). // 获取BulkService对象Index((model.User{}).Index()). // 指明要操作的索引Refresh(true)for _, user : range userList {// 与批量删除主要就是这一行不同bulk : elastic.NewBulkCreateRequest().Doc(user)bulkService.Add(bulk)}bulkResp, err : bulkService.Do(context.Background())if err ! nil {fmt.Println(err)return}fmt.Printf(%#v\n, bulkResp)}执行
package mainimport (golang-trick/34-go-es/coregolang-trick/34-go-es/docs
)func main() {core.InitEsConn()// indexs.CreateIndex(user_index)//docs.CreateDoc()//docs.DeleteDoc(d6ldWYwBwPESsKz-qasv)// docs.BatchDeleteDoc([]string{eKmUWYwBwPESsKz-8qsp, eamVWYwBwPESsKz-DKve})docs.BatchCreateDoc()
} 五、文档查询
列表查询
返回结构如下主要是res.Hits.Hits中的一条记录是SearchHit对象里面的Source为我们的文档数据json.RawMessage就是[]byte的别名而已所以可以直接转为string或者反序列化到我们的结构体对象中
代码如下
func FindDoc() {query : elastic.NewBoolQuery()res, err : core.EsClient.Search((model.User{}).Index()). // 指定索引且表明是查询操作Query(query). // 查询条件From(0). // 分页操作Size(10).Do(context.Background())if err ! nil {fmt.Println(err)return}count : res.Hits.TotalHits.Valuefmt.Println(count)for _, hit : range res.Hits.Hits {fmt.Println(string(hit.Source))}
}
执行
package mainimport (golang-trick/34-go-es/coregolang-trick/34-go-es/docs
)func main() {core.InitEsConn()// indexs.CreateIndex(user_index)//docs.CreateDoc()//docs.DeleteDoc(d6ldWYwBwPESsKz-qasv)// docs.BatchDeleteDoc([]string{eKmUWYwBwPESsKz-8qsp, eamVWYwBwPESsKz-DKve})// docs.BatchCreateDoc()docs.FindDoc()
} 精确匹配
精确匹配只能对mapping中定义为keyword的字段生效,比如下面我们只能对user_name使用精确匹配对nick_name字段无法使用所以在设计索引时如果已知后面会对某个字段进行精确匹配应该将其设置为keyword类型 代码
func FindDoc() {limit : 10page : 1from : (page - 1) * limit//query : elastic.NewBoolQuery()query : elastic.NewTermQuery(user_name, lym)res, err : core.EsClient.Search((model.User{}).Index()). // 指定索引且表明是查询操作Query(query). // 查询条件From(from). // 分页操作Size(limit).Do(context.Background())if err ! nil {fmt.Println(err)return}count : res.Hits.TotalHits.Valuefmt.Println(count)for _, hit : range res.Hits.Hits {fmt.Println(string(hit.Source))}
}执行 如果换成nick_name即使写为了完全正确的夜空中最亮的星也是匹配不到结果的因为nick_name的type是text不是keyword
模糊匹配 主要是查text也能查keyword 模糊匹配keyword字段是需要查完整的 匹配text字段则不用搜完整的也会搜出很多
代码
查询对象换为NewMatchQuery即可 嵌套字段的搜索
我们在创建索引时并没有指定title字段的mapping但是因为在插入文档时带了title字段es会自动帮我们将其加入到mapping中且是一个嵌套类型如下
title: {type: text,fields: {keyword: {type: keyword,ignore_above: 256}}
}因为title是text类型只能模糊匹配但是需要精确匹配的时候也能通过title.keyword的形式进行精确匹配如下
query : elastic.NewTermQuery(title.keyword, 学习创建索引2) // 精确匹配
//query : elastic.NewMatchQuery(title, 学习) // 模糊匹配六、 更新文档
更新文档我们一般都是已经知道文档id了所以就是根据文档id进行更新传入map即可
更新前 代码
func UpdateDoc(id string) {res, err : core.EsClient.Update().Index((model.User{}).Index()).Id(id).Doc(map[string]any{user_name: lymUpdate,}).Do(context.Background())if err ! nil {fmt.Println(err)return}fmt.Printf(%#v\n, res)
}执行
package mainimport (golang-trick/34-go-es/coregolang-trick/34-go-es/docs
)func main() {core.InitEsConn()// indexs.CreateIndex(user_index)//docs.CreateDoc()//docs.DeleteDoc(d6ldWYwBwPESsKz-qasv)// docs.BatchDeleteDoc([]string{eKmUWYwBwPESsKz-8qsp, eamVWYwBwPESsKz-DKve})// docs.BatchCreateDoc()// docs.FindDoc()docs.UpdateDoc(eqmeWYwBwPESsKz-nasc)
}
更新后