在今天的文章中,我将介绍如何使用 Go 语言来对 Elasticsearch 进行搜索。首先,我假设你已经对 Elastic Stack 有一定的了解。Elasticsearch 获得了极大的欢迎。 在关系数据库中搜索始终会遇到有关可伸缩性和性能的问题。Elasticsearch 是 NoSQL 数据库,在解决这些问题方面非常成功。 它提供了出色的可拓展性和性能,而最突出的功能之一就是相关性分析,它使搜索结果具有很大的灵活性。
Elastic Stack
安装 Elasticsearch 及 Kibana
如果你还没有安装好自己的 Elasticsearch 及 Kibana 的话,那么请参阅我之前的文章:
一旦完成好 Elasticsearch 及 Kibana 的安装,我们可以在浏览器中输入地址 http://localhost:9200 来进行访问:
我们也可以直接访问 Kibana:
创建你的第一个索引 (index)
在 Elasticsearch中,索引类似于数据库。 以前,elasticsearch 中有一个叫做 type 的表。 但是由于类型已在当前版本中删除,因此现在只有索引。
现在感到困惑吗? 不用了 简而言之,只需考虑只需要索引,然后再将数据插入 Elasticsearch 即可。
现在,我们将通过下面的查询创建一个名为 students 的索引。
PUT students
上面的命令的响应为:
-
{
-
"acknowledged" :
true,
-
"shards_acknowledged" :
true,
-
"index" :
"students"
-
}
它已经为我们创建了一个名为 students 的索引。在接下的步骤中,我们将想这个索引里写入一些数据,也就是一些文档。
写入文档到索引中
首先,我们现在要做的是用文档填充我们的 Elasticsearch 索引。 如果你不熟悉该定义,请知道它与数据库中的行非常相似。我们使用如下的命令来把数据导入到 Elasticsearch 中:
-
POST students/_
doc
-
{
-
"name":
"Alice",
-
"age":
17,
-
"average_score":
85
-
}
上面的命令的响应为:
-
{
-
"_index" :
"students",
-
"_type" :
"_doc",
-
"_id" :
"cMpCSnUBzapZdaLVYfwW",
-
"_version" :
1,
-
"result" :
"created",
-
"_shards" : {
-
"total" :
2,
-
"successful" :
1,
-
"failed" :
0
-
},
-
"_seq_no" :
0,
-
"_primary_term" :
1
-
}
你的 Elasticsearch 现在应该有一个文档。 我们将需要在索引 students 中插入更多数据。 当然,我们不会一个接一个地插入我们的学生数据-这很麻烦!
Elasticsearch 特别准备了一个 bulk API,以便一次发送多个请求。 让我们用它一次插入多个数据。
-
POST students/_
bulk
-
{
"index":{ } }
-
{
"name":
"john doe",
"age":18,
"average_score":77.7 }
-
{
"index":{} }
-
{
"name":
"bob",
"age":16,
"average_score":65.5 }
-
{
"index":{} }
-
{
"name":
"mary doe",
"age":18,
"average_score":97.7 }
-
{
"index":{} }
-
{
"name":
"eve",
"age":15,
"average_score":98.9 }
我们可以通过如下的命令来检查已经输入的 5 个文档:
GET students/_count
搜索索引文档
我们终于在 Elasticsearch 中填充了更多学生的数据。 现在,让我们来做一下 Elasticsearch 众所周知的事情:我们将尝试在 Elasticsearch 中搜索刚刚插入的数据。
Elasticsearch 支持多种类型的搜索机制,但在此示例中,我们将使用简单的匹配查询。
让我们通过点击以下 API 开始搜索:
-
GET students/_search
-
{
-
"query": {
-
"match": {
-
"name":
"doe"
-
}
-
}
-
}
上面的命令显示:
-
{
-
"took" :
0,
-
"timed_out" :
false,
-
"_shards" : {
-
"total" :
1,
-
"successful" :
1,
-
"skipped" :
0,
-
"failed" :
0
-
},
-
"hits" : {
-
"total" : {
-
"value" :
2,
-
"relation" :
"eq"
-
},
-
"max_score" :
0.74487394,
-
"hits" : [
-
{
-
"_index" :
"students",
-
"_type" :
"_doc",
-
"_id" :
"hstFSnUBzapZdaLVQQCN",
-
"_score" :
0.74487394,
-
"_source" : {
-
"name" :
"john doe",
-
"age" :
18,
-
"average_score" :
77.7
-
}
-
},
-
{
-
"_index" :
"students",
-
"_type" :
"_doc",
-
"_id" :
"iMtFSnUBzapZdaLVQQCN",
-
"_score" :
0.74487394,
-
"_source" : {
-
"name" :
"mary doe",
-
"age" :
18,
-
"average_score" :
97.7
-
}
-
}
-
]
-
}
-
}
上面将返回你的查询以及与你的相应查询匹配的学生数据。 现在,恭喜你你已经正式成为一名搜索工程师!
让我们使用 Go
如果你已经达到这一部分,那么你应该已经掌握了使用 Elasticsearch 的最低限度的概念。 现在,我们将在 Go 中实现 Elasticsearch。实施 Elasticsearch 的一种非常原始的方法是,你可以继续将 HTTP 请求发送到你的 Elasticsearch IP 中。 但是我们不会那样做。
我发现这个非常有用的库对于在 Go 中实现 Elasticsearch 很有帮助。 在继续执行 Go 模块之前,应先安装该库。我们可以使用如下的命令来进行安装:
go get github.com/olivere/elastic
创建你自己的 struct
首先,你肯定需要为模型制作一个结构。 在此示例中,我们将使用与先前示例相同的建模,在本例中为 Student 结构。
-
package main
-
-
type Student
struct {
-
Name
string
`json:"name"`
-
Age
int64
`json:"age"`
-
AverageScore
float64
`json:"average_score"`
-
}
创建客户端连接
现在,让我们创建一个函数,该函数将允许我们初始化 ES Client 连接。
如果你在本地主机外部有一个正在运行的 Elasticsearch 实例,则只需更改 SetURL 中的部分即可。
-
func GetESClient() (*elastic.Client, error) {
-
-
client, err := elastic.NewClient(elastic.SetURL(
"http://localhost:9200"),
-
elastic.SetSniff(
false),
-
elastic.SetHealthcheck(
false))
-
-
fmt.Println(
"ES initialized...")
-
-
return client, err
-
-
}
数据插入
之后,我们要做的第一件事就是尝试通过 Go 将数据插入到 Elasticsearch 中。 我们将制作一个 Student 模型,并将其插入到我们的 Elasticsearch 客户端中。
insert.go
-
package main
-
-
import (
-
"context"
-
"encoding/json"
-
"fmt"
-
"github.com/olivere/elastic"
-
)
-
-
type Student
struct {
-
Name
string
`json:"name"`
-
Age
int64
`json:"age"`
-
AverageScore
float64
`json:"average_score"`
-
}
-
-
func GetESClient() (*elastic.Client, error) {
-
-
client, err := elastic.NewClient(elastic.SetURL(
"http://localhost:9200"),
-
elastic.SetSniff(
false),
-
elastic.SetHealthcheck(
false))
-
-
fmt.Println(
"ES initialized...")
-
-
return client, err
-
-
}
-
-
func main() {
-
-
ctx := context.Background()
-
esclient, err := GetESClient()
-
if err !=
nil {
-
fmt.Println(
"Error initializing : ", err)
-
panic(
"Client fail ")
-
}
-
-
//creating student object
-
newStudent := Student{
-
Name:
"Gopher doe",
-
Age:
10,
-
AverageScore:
99.9,
-
}
-
-
dataJSON, err := json.Marshal(newStudent)
-
js :=
string(dataJSON)
-
_, err = esclient.Index().
-
Index(
"students").
-
BodyJson(js).
-
Do(ctx)
-
-
if err !=
nil {
-
panic(err)
-
}
-
-
fmt.Println(
"[Elastic][InsertProduct]Insertion Successful")
-
-
}
我们可以使用它如下的命令来进行运行:
go run insert.go
上面的应用显示:
-
$ go run insert.go
-
ES initialized...
-
[
Elastic][
InsertProduct]Insertion Successful
我们可以通过 Kibana 来验证一下新的文档是否已经被成功地写入:
-
GET students/_search
-
{
-
"query": {
-
"match": {
-
"name":
"Gopher doe"
-
}
-
}
-
}
上面显示我们的文档已经被成功地写入到 Elasticsearch 之中了。
查询数据
最后,我们可以进行一些搜索。 下面的代码可能看起来有些复杂。 但是请放心,在你仔细地进行操作之后,它对你会更有意义。 在下面的示例中,我将使用基本的匹配查询。
search.go
-
package main
-
-
import (
-
"context"
-
"encoding/json"
-
"fmt"
-
"github.com/olivere/elastic"
-
)
-
-
type Student
struct {
-
Name
string
`json:"name"`
-
Age
int64
`json:"age"`
-
AverageScore
float64
`json:"average_score"`
-
}
-
-
func GetESClient() (*elastic.Client, error) {
-
-
client, err := elastic.NewClient(elastic.SetURL(
"http://localhost:9200"),
-
elastic.SetSniff(
false),
-
elastic.SetHealthcheck(
false))
-
-
fmt.Println(
"ES initialized...")
-
-
return client, err
-
-
}
-
-
func main() {
-
-
ctx := context.Background()
-
esclient, err := GetESClient()
-
if err !=
nil {
-
fmt.Println(
"Error initializing : ", err)
-
panic(
"Client fail ")
-
}
-
-
var students []Student
-
-
searchSource := elastic.NewSearchSource()
-
searchSource.Query(elastic.NewMatchQuery(
"name",
"Doe"))
-
-
/* this block will basically print out the es query */
-
queryStr, err1 := searchSource.Source()
-
queryJs, err2 := json.Marshal(queryStr)
-
-
if err1 !=
nil || err2 !=
nil {
-
fmt.Println(
"[esclient][GetResponse]err during query marshal=", err1, err2)
-
}
-
fmt.Println(
"[esclient]Final ESQuery=\n",
string(queryJs))
-
/* until this block */
-
-
searchService := esclient.Search().Index(
"students").SearchSource(searchSource)
-
-
searchResult, err := searchService.Do(ctx)
-
if err !=
nil {
-
fmt.Println(
"[ProductsES][GetPIds]Error=", err)
-
return
-
}
-
-
for _, hit :=
range searchResult.Hits.Hits {
-
var student Student
-
err := json.Unmarshal(hit.Source, &student)
-
if err !=
nil {
-
fmt.Println(
"[Getting Students][Unmarshal] Err=", err)
-
}
-
-
students =
append(students, student)
-
}
-
-
if err !=
nil {
-
fmt.Println(
"Fetching student fail: ", err)
-
}
else {
-
for _, s :=
range students {
-
fmt.Printf(
"Student found Name: %s, Age: %d, Score: %f \n", s.Name, s.Age, s.AverageScore)
-
}
-
}
-
-
}
我们使用如下的命令来运行:
go run search.go
查询应像这样打印出来:
-
ES initialized...
-
[esclient]
Final ESQuery=
-
{
"query":{
"match":{
"name":{
"query":
"Doe"}}}}
是的,该查询就是将要发布到 Elasticsearch 中的内容。如果从一开始就遵循我的示例,则查询结果也应如下所示:
-
Student found Name:
john
doe,
Age:
18
,
Score:
77.700000
-
Student found Name:
mary
doe,
Age:
18
,
Score:
97.700000
-
Student found Name:
Gopher
doe,
Age:
10
,
Score:
99.900000
Hooray! 我们终于完成了第一个使用 Golang 把数据导入到 Elasticsearch 并进行搜索的过程。这个过程非常简单!
如果你想了解更多关于 Elasticsearch 的知识以及其它更为复杂的 DSL 查询,请阅读我的另外一篇文章 “Elastic:菜鸟上手指南”。
转载:https://blog.csdn.net/UbuntuTouch/article/details/109203614