Bootstrap

【Go语言】elasticsearch的学习

一、es的连接

       我这里使用的是云服务器上的es,所以在使用 Go 来进行连接的时候,我们需要将云服务器的IP地址知道,代码如下:

func EsConnect() {
	// 创建一个 Elasticsearch 客户端连接
	client, err := elastic.NewClient(
		elastic.SetURL("http://<your ip address>:9200"), // ES 服务地址
		elastic.SetSniff(false),                   // 禁用节点嗅探
	)
	if err != nil {
		log.Fatalf("Error creating the client: %s", err)
	}
	global.ESClient = client
}

二、索引操作

2.1 常见的类型

{
  "mappings": {
    "properties": {
      "title": { 
        "type": "text" // 查询的时候是分词匹配
      },
      "key": { 
        "type": "keyword" // 完整匹配
      },
      "user_id": {
        "type": "integer"
      },
      "created_at":{
        "type": "date",
        "null_value": "null",
        "format": "[yyyy-MM-dd HH:mm:ss]"
      }
    }
  }
}

2.2 创建索引

func CreateIndex() {
	createIndex, err := global.ESClient.CreateIndex("user_index").
        BodyString(models.UserModel{}.
        Mapping()).Do(context.Background())
	if err != nil {
		panic(err)
		return
	}
	fmt.Println(createIndex)
}

2.3 判断索引是否存在

// ExistsIndex 判断索引是否存在
func ExistsIndex(index string) bool {
  exists, _ := global.ESClient.
     IndexExists(index).Do(context.Background())
  return exists
}

2.4 删除索引

func DeleteIndex(index string) {
  _, err := global.ESClient.
    DeleteIndex(index).Do(context.Background())
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(index, "索引删除成功")
}

三、文档操作

3.1 添加文档

3.1.1 添加单个文档

func DocCreate() {
  user := models.UserModel{
    ID:        12,
    UserName:  "lisi",
    Age:       23,
    NickName:  "夜空中最亮的lisi",
    CreatedAt: time.Now().Format("2006-01-02 15:04:05"),
    Title:     "今天天气很不错",
  }
  indexResponse, err :=         
     global.ESClient.Index().
     Index(user.Index()).
     BodyJson(user).Do(context.Background())
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Printf("%#v\n", indexResponse)
}

       我们在添加文档中,如果是 mapping 里面没有的字段,那么 es 会自动创建这个字段对应的 mapping。

3.1.2 批量添加文档

func DocCreateBatch() {

  list := []models.UserModel{
    {
      ID:        12,
      UserName:  "fengfeng",
      NickName:  "夜空中最亮的枫枫",
      CreatedAt: time.Now().Format("2006-01-02 15:04:05"),
    },
    {
      ID:        13,
      UserName:  "lisa",
      NickName:  "夜空中最亮的丽萨",
      CreatedAt: time.Now().Format("2006-01-02 15:04:05"),
    },
  }

  bulk := global.ESClient.Bulk().Index(models.UserModel{}.
        Index()).Refresh("true")
  for _, model := range list {
    req := elastic.NewBulkCreateRequest().Doc(model)
    bulk.Add(req)
  }
  res, err := bulk.Do(context.Background())
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(res.Succeeded())
}

3.2 删除文档

3.2.1 根据id删除

func DocDelete() {

  deleteResponse, err := global.ESClient.Delete().
       Index(models.UserModel{}.Index()).Id("tmcqfYkBWS69Op6Q4Z0t").
       Refresh("true").Do(context.Background())
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(deleteResponse)
}

如果我们要删除是文档不存在,我们会报 404 错误。 

3.2.2 根据id批量删除

func DocDeleteBatch() {
  idList := []string{
    "tGcofYkBWS69Op6QHJ2g",
    "tWcpfYkBWS69Op6Q050w",
  }
  bulk := global.ESClient.Bulk().
    Index(models.UserModel{}.Index()).Refresh("true")
  for _, s := range idList {
    req := elastic.NewBulkDeleteRequest().Id(s)
    bulk.Add(req)
  }
  res, err := bulk.Do(context.Background())
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(res.Succeeded())  // 实际删除的文档切片
}

如果我们需要删除的文档不存在,不会有错误,res.Succeeded() 为空。

3.3 文档查询

3.3.1 列表查询

func DocFind() {

  limit := 2
  page := 4
  from := (page - 1) * limit

  query := elastic.NewBoolQuery()
  res, err := global.ESClient.Search(models.UserModel{}.Index()).
    Query(query).From(from).Size(limit).Do(context.Background())
  if err != nil {
    fmt.Println(err)
    return
  }
  count := res.Hits.TotalHits.Value  // 总数
  fmt.Println(count)
  for _, hit := range res.Hits.Hits {
    fmt.Println(string(hit.Source))
  }
}

3.3.2 精确匹配

精确匹配是针对 keyword 字段,而不是针对 text 字段。

query := elastic.NewTermQuery("user_name", "fengfeng")

3.3.3 模糊匹配

       主要是查 text,但是也可以查 keyword,模糊匹配 keyword 字段,是需要查完整的,匹配 text 字段则不用,搜完整的也会搜出很多。

query := elastic.NewMatchQuery("nick_name", "夜空中最亮的枫枫")

3.3.4 嵌套字段的搜索

"title": {
    "type": "text",
    "fields": {
        "keyword": {
            "type": "keyword",
            "ignore_above": 256
        }
    }
},

       因为 title 是 text 类型,只能模糊匹配,但是需要精确匹配的时候,也能通过 title.keyword 的形式来进行精确匹配。

query := elastic.NewTermQuery("title.keyword", "这是我的枫枫") // 精确匹配
//query := elastic.NewMatchQuery("title", "这是我的枫枫")  // 模糊匹配

3.4 文档更新

func DocUpdate() {
  res, err := global.ESClient.Update().Index(models.UserModel{}.Index()).
    Id("vmdnfYkBWS69Op6QEp2Y").Doc(map[string]any{
    "user_name": "你好枫枫",
  }).Do(context.Background())
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Printf("%#v\n", res)
}

;