飞道的博客

Elasticsearch:运用 Go 语言实现 Elasticsearch 搜索

311人阅读  评论(0)

在今天的文章中,我将介绍如何使用 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

上面的命令的响应为:


  
  1. {
  2. "acknowledged" : true,
  3. "shards_acknowledged" : true,
  4. "index" : "students"
  5. }

它已经为我们创建了一个名为 students 的索引。在接下的步骤中,我们将想这个索引里写入一些数据,也就是一些文档。

 

写入文档到索引中

首先,我们现在要做的是用文档填充我们的 Elasticsearch 索引。 如果你不熟悉该定义,请知道它与数据库中的行非常相似。我们使用如下的命令来把数据导入到 Elasticsearch 中:


  
  1. POST students/_ doc
  2. {
  3. "name": "Alice",
  4. "age": 17,
  5. "average_score": 85
  6. }

上面的命令的响应为:


  
  1. {
  2. "_index" : "students",
  3. "_type" : "_doc",
  4. "_id" : "cMpCSnUBzapZdaLVYfwW",
  5. "_version" : 1,
  6. "result" : "created",
  7. "_shards" : {
  8. "total" : 2,
  9. "successful" : 1,
  10. "failed" : 0
  11. },
  12. "_seq_no" : 0,
  13. "_primary_term" : 1
  14. }

你的 Elasticsearch 现在应该有一个文档。 我们将需要在索引 students 中插入更多数据。 当然,我们不会一个接一个地插入我们的学生数据-这很麻烦!

Elasticsearch 特别准备了一个 bulk API,以便一次发送多个请求。 让我们用它一次插入多个数据。


  
  1. POST students/_ bulk
  2. { "index":{ } }
  3. { "name": "john doe", "age":18, "average_score":77.7 }
  4. { "index":{} }
  5. { "name": "bob", "age":16, "average_score":65.5 }
  6. { "index":{} }
  7. { "name": "mary doe", "age":18, "average_score":97.7 }
  8. { "index":{} }
  9. { "name": "eve", "age":15, "average_score":98.9 }

我们可以通过如下的命令来检查已经输入的 5 个文档:

GET students/_count

搜索索引文档

我们终于在 Elasticsearch 中填充了更多学生的数据。 现在,让我们来做一下 Elasticsearch 众所周知的事情:我们将尝试在 Elasticsearch 中搜索刚刚插入的数据。

Elasticsearch 支持多种类型的搜索机制,但在此示例中,我们将使用简单的匹配查询。

让我们通过点击以下 API 开始搜索:


  
  1. GET students/_search
  2. {
  3. "query": {
  4. "match": {
  5. "name": "doe"
  6. }
  7. }
  8. }

上面的命令显示:


  
  1. {
  2. "took" : 0,
  3. "timed_out" : false,
  4. "_shards" : {
  5. "total" : 1,
  6. "successful" : 1,
  7. "skipped" : 0,
  8. "failed" : 0
  9. },
  10. "hits" : {
  11. "total" : {
  12. "value" : 2,
  13. "relation" : "eq"
  14. },
  15. "max_score" : 0.74487394,
  16. "hits" : [
  17. {
  18. "_index" : "students",
  19. "_type" : "_doc",
  20. "_id" : "hstFSnUBzapZdaLVQQCN",
  21. "_score" : 0.74487394,
  22. "_source" : {
  23. "name" : "john doe",
  24. "age" : 18,
  25. "average_score" : 77.7
  26. }
  27. },
  28. {
  29. "_index" : "students",
  30. "_type" : "_doc",
  31. "_id" : "iMtFSnUBzapZdaLVQQCN",
  32. "_score" : 0.74487394,
  33. "_source" : {
  34. "name" : "mary doe",
  35. "age" : 18,
  36. "average_score" : 97.7
  37. }
  38. }
  39. ]
  40. }
  41. }

上面将返回你的查询以及与你的相应查询匹配的学生数据。 现在,恭喜你你已经正式成为一名搜索工程师!

 

让我们使用 Go

如果你已经达到这一部分,那么你应该已经掌握了使用 Elasticsearch 的最低限度的概念。 现在,我们将在 Go 中实现 Elasticsearch。实施 Elasticsearch 的一种非常原始的方法是,你可以继续将 HTTP 请求发送到你的 Elasticsearch IP 中。 但是我们不会那样做。

我发现这个非常有用的库对于在 Go 中实现 Elasticsearch 很有帮助。 在继续执行 Go 模块之前,应先安装该库。我们可以使用如下的命令来进行安装:

go get github.com/olivere/elastic

创建你自己的 struct

首先,你肯定需要为模型制作一个结构。 在此示例中,我们将使用与先前示例相同的建模,在本例中为 Student 结构。


  
  1. package main
  2. type Student struct {
  3. Name string `json:"name"`
  4. Age int64 `json:"age"`
  5. AverageScore float64 `json:"average_score"`
  6. }

创建客户端连接

现在,让我们创建一个函数,该函数将允许我们初始化 ES Client 连接。
如果你在本地主机外部有一个正在运行的 Elasticsearch 实例,则只需更改 SetURL 中的部分即可。


  
  1. func GetESClient() (*elastic.Client, error) {
  2. client, err := elastic.NewClient(elastic.SetURL( "http://localhost:9200"),
  3. elastic.SetSniff( false),
  4. elastic.SetHealthcheck( false))
  5. fmt.Println( "ES initialized...")
  6. return client, err
  7. }

数据插入

之后,我们要做的第一件事就是尝试通过 Go  将数据插入到 Elasticsearch 中。 我们将制作一个 Student 模型,并将其插入到我们的 Elasticsearch 客户端中。

insert.go


  
  1. package main
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "github.com/olivere/elastic"
  7. )
  8. type Student struct {
  9. Name string `json:"name"`
  10. Age int64 `json:"age"`
  11. AverageScore float64 `json:"average_score"`
  12. }
  13. func GetESClient() (*elastic.Client, error) {
  14. client, err := elastic.NewClient(elastic.SetURL( "http://localhost:9200"),
  15. elastic.SetSniff( false),
  16. elastic.SetHealthcheck( false))
  17. fmt.Println( "ES initialized...")
  18. return client, err
  19. }
  20. func main() {
  21. ctx := context.Background()
  22. esclient, err := GetESClient()
  23. if err != nil {
  24. fmt.Println( "Error initializing : ", err)
  25. panic( "Client fail ")
  26. }
  27. //creating student object
  28. newStudent := Student{
  29. Name: "Gopher doe",
  30. Age: 10,
  31. AverageScore: 99.9,
  32. }
  33. dataJSON, err := json.Marshal(newStudent)
  34. js := string(dataJSON)
  35. _, err = esclient.Index().
  36. Index( "students").
  37. BodyJson(js).
  38. Do(ctx)
  39. if err != nil {
  40. panic(err)
  41. }
  42. fmt.Println( "[Elastic][InsertProduct]Insertion Successful")
  43. }

我们可以使用它如下的命令来进行运行:

go run insert.go

上面的应用显示:


  
  1. $ go run insert.go
  2. ES initialized...
  3. [ Elastic][ InsertProduct]Insertion Successful

我们可以通过 Kibana 来验证一下新的文档是否已经被成功地写入:


  
  1. GET students/_search
  2. {
  3. "query": {
  4. "match": {
  5. "name": "Gopher doe"
  6. }
  7. }
  8. }

上面显示我们的文档已经被成功地写入到 Elasticsearch 之中了。

 

查询数据

最后,我们可以进行一些搜索。 下面的代码可能看起来有些复杂。 但是请放心,在你仔细地进行操作之后,它对你会更有意义。 在下面的示例中,我将使用基本的匹配查询。

search.go


  
  1. package main
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "github.com/olivere/elastic"
  7. )
  8. type Student struct {
  9. Name string `json:"name"`
  10. Age int64 `json:"age"`
  11. AverageScore float64 `json:"average_score"`
  12. }
  13. func GetESClient() (*elastic.Client, error) {
  14. client, err := elastic.NewClient(elastic.SetURL( "http://localhost:9200"),
  15. elastic.SetSniff( false),
  16. elastic.SetHealthcheck( false))
  17. fmt.Println( "ES initialized...")
  18. return client, err
  19. }
  20. func main() {
  21. ctx := context.Background()
  22. esclient, err := GetESClient()
  23. if err != nil {
  24. fmt.Println( "Error initializing : ", err)
  25. panic( "Client fail ")
  26. }
  27. var students []Student
  28. searchSource := elastic.NewSearchSource()
  29. searchSource.Query(elastic.NewMatchQuery( "name", "Doe"))
  30. /* this block will basically print out the es query */
  31. queryStr, err1 := searchSource.Source()
  32. queryJs, err2 := json.Marshal(queryStr)
  33. if err1 != nil || err2 != nil {
  34. fmt.Println( "[esclient][GetResponse]err during query marshal=", err1, err2)
  35. }
  36. fmt.Println( "[esclient]Final ESQuery=\n", string(queryJs))
  37. /* until this block */
  38. searchService := esclient.Search().Index( "students").SearchSource(searchSource)
  39. searchResult, err := searchService.Do(ctx)
  40. if err != nil {
  41. fmt.Println( "[ProductsES][GetPIds]Error=", err)
  42. return
  43. }
  44. for _, hit := range searchResult.Hits.Hits {
  45. var student Student
  46. err := json.Unmarshal(hit.Source, &student)
  47. if err != nil {
  48. fmt.Println( "[Getting Students][Unmarshal] Err=", err)
  49. }
  50. students = append(students, student)
  51. }
  52. if err != nil {
  53. fmt.Println( "Fetching student fail: ", err)
  54. } else {
  55. for _, s := range students {
  56. fmt.Printf( "Student found Name: %s, Age: %d, Score: %f \n", s.Name, s.Age, s.AverageScore)
  57. }
  58. }
  59. }

我们使用如下的命令来运行:

go run search.go

查询应像这样打印出来:


  
  1. ES initialized...
  2. [esclient] Final ESQuery=
  3. { "query":{ "match":{ "name":{ "query": "Doe"}}}}

是的,该查询就是将要发布到 Elasticsearch 中的内容。如果从一开始就遵循我的示例,则查询结果也应如下所示:


  
  1. Student found Name: john doe, Age: 18 , Score: 77.700000
  2. Student found Name: mary doe, Age: 18 , Score: 97.700000
  3. Student found Name: Gopher doe, Age: 10 , Score: 99.900000

Hooray! 我们终于完成了第一个使用 Golang 把数据导入到 Elasticsearch 并进行搜索的过程。这个过程非常简单!

如果你想了解更多关于 Elasticsearch 的知识以及其它更为复杂的 DSL 查询,请阅读我的另外一篇文章 “Elastic:菜鸟上手指南”。


转载:https://blog.csdn.net/UbuntuTouch/article/details/109203614
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场