乐趣区

关于golang:ElasticSearch-查询使用

1. 基本概念
1.1 index(索引)
在 Elasticsearch 中索引(index)相似 mysql 的表,代表文档数据的汇合,文档指的是 ES 中存储的一条数据。

1.2 Document(文档)
Elasticsearch 是面向文档的数据库,文档是最根本的存储单元,文档相似 mysql 表中的一行数据。简略的说在 ES 中,文档指的就是一条 JSON 数据。

1.3 Field(文档字段)
文档由多个 json 字段(Field)组成,这里的字段相似 mysql 中表的字段。

1.4 mapping (映射)
Elasticsearch 的 mapping (映射)相似 mysql 中的表构造定义,每个索引都有一个映射规定,咱们能够通过定义索引的映射规定,提前定义好文档的 json 构造和字段类型,如果没有定义索引的映射规定,Elasticsearch 会在写入数据的时候,依据咱们写入的数据字段揣测出对应的字段类型,相当于主动定义索引的映射规定。

类比 MYSQL 存储构造:


元数据的字段名都是以下划线结尾的
常见的元数据如下:

  1. _index – 代表以后 JSON 文档所属的文档名字
  2. _type – 代表以后 JSON 文档所属的类型, 尽管新版 ES 废除了 type 的用法, 然而元数据还是能够看到
  3. _id – 文档惟一 Id, 如果咱们没有为文档指定 id, 零碎会主动生成
  4. _source – 代表咱们插入进去的 JSON 数据
  5. _version – 文档的版本号, 每批改一次文档数据, 字段就会加 1, 这个字段新版的 ES 曾经不应用了
  6. _seq_no – 文档的版本号, 代替老的_version 字段
  7. _primary_term – 文档所在主分区, 这个能够跟_seq_no 字段搭配实现乐观锁

开发实战:
第三方开发者保护的库 olivere/elastic
官网的 Golang 客户端 go-elasticsearch

olivere/elastic 应用

package main

import (
   "context"
   "fmt"
   "github.com/olivere/elastic/v7"
   "log"
   "os"
   "reflect"
   "time"
)

// 查问后果定义
type QueryInfo struct {
   Domain string `json:"domain"`     // 查问域名
   ClientIP string `json:"client_ip"` // 起源 IP
   Scheme string `json:"scheme"`     // 协定类型
   Referer string `json:"referer"`       // 申请起源
   Url string `json:"url"`             // 申请 url
   HttpCode string `json:"http_code"` // 返回状态码
   Method string `json:"method"`     // 申请办法
}

// 初始化变量
var (
   queryInfo QueryInfo
   indexName = "chegva_ngx_proxy_log"
   // es 集群地址列表:https://sgp.api.es.che/product/es/cluster-list
   apiAddresses = []string{"http://sgp.api.es.che"} // elasticsearch 服务地址,多个服务地址应用逗号分隔
   username, password = "anzhihe", "anzhihe"
   client *elastic.Client
   res *elastic.SearchResult
   err error
   ctx context.Context
)

func init() {
   // 连贯 es 集群
   client, err = elastic.NewClient(elastic.SetURL(apiAddresses...),
      elastic.SetBasicAuth(username, password),
      // 容许您指定弹性是否应该定期检查集群(默认为真)elastic.SetSniff(false),
      // 设置监控查看工夫距离
      elastic.SetHealthcheckInterval(10*time.Second),
      // 设置谬误日志输入
      elastic.SetErrorLog(log.New(os.Stderr, "ELASTIC", log.LstdFlags)),
      // 设置 info 日志输入
      elastic.SetInfoLog(log.New(os.Stdout, "", log.LstdFlags)))

   if err != nil {fmt.Println("连贯失败:%v\n", err)
      panic(err)
   }

   fmt.Println("连贯胜利", client)
}

// 查问日志
func Search() {
   // 执行 ES 申请须要提供一个上下文对象
   ctx = context.Background()

   // 创立 bool 组合查问;must 条件相似 SQL 的 and;must_not 与 must 作用相同;should 相似 SQL 中的 or,只有匹配区中一个就行
   //boolQuery := elastic.NewBoolQuery().Must()

   // 创立查问
   // term 准确查问;terms 多值查问相似 SQL 的 in 查问
   domainQuery := elastic.NewTermQuery("domain", "api.pay.chegva.com")
   // Match 查问,匹配单个字段
   urlQuery := elastic.NewMatchQuery("url", "/pay/")
   // Ranges 范畴查问
   timeQuery := elastic.NewRangeQuery("timestamp").
      Gte("2022-02-22").
      Lte("now").
      Format("yyyy-MM-dd")

   // Filter 多重条件筛选
   boolSearch := elastic.NewBoolQuery().
      Filter(domainQuery).
      Filter(urlQuery).
      Filter(timeQuery)

   // 设置 bool 查问的 must 条件, 组合了两个子查问
   //boolQuery.Must(domainQuery, timeQuery)

   res, err = client.Search().
      Index(indexName).
      Query(boolSearch).
      From(0).Size(10). // 拿前 10 个后果,默认不能大于 10000
      Pretty(true).
      Do(ctx) // 执行
      
   if err != nil {panic(err)
   }
   
   total := res.TotalHits()
   fmt.Printf("Found %d results\n", total)
   if total > 0 {printQueryInfo(res, err)
   } else {fmt.Println("Not found!")
   }
}

// 打印查问到的输入
func printQueryInfo(res *elastic.SearchResult, err error) {
   if err != nil {print(err.Error())
      return
   }
   // 通过 Each 办法,将 es 后果的 json 构造转换成 struct 对象
   for _, item := range res.Each(reflect.TypeOf(queryInfo)) { // 从搜寻后果中取数据的办法
      if q, ok := item.(QueryInfo); ok {fmt.Printf("%#v\n", q)
      }
   }
}

func main() {Search()
}

官网库 go-elasticsearch 应用:

package main

import (
   "bytes"
   "encoding/json"
   "fmt"
   "github.com/elastic/go-elasticsearch/v7"
   "log"
)

func main() {
   cfg := elasticsearch.Config{Addresses: []string{"http://sgp.api.es.che",},
      Username: "anzhihe",
      Password: "anzhihe",
   }
   var buf bytes.Buffer

   query := map[string]interface{}{"query": map[string]interface{}{"match": map[string]interface{}{"domain": "api.pay.chegva.com",},
      },
   }
   if err := json.NewEncoder(&buf).Encode(query); err != nil {log.Fatalf("Error encoding query: %s", err)
   }
   es, _ := elasticsearch.NewClient(cfg)
   log.Println(es.Info())
   result, err := es.Search(es.Search.WithIndex("chegva_ngx_proxy_log"), es.Search.WithBody(&buf))
   if err != nil {fmt.Println(err)
   }
   fmt.Println(result)
}

除上述应用计划,还能够应用 Http 申请接口:

func query(url  string,username string,password string) {jsonData := `{"query": {"term": {"request.data.id": "953c142cac566635120578a"}}}`
    req, _ := http.NewRequest("POST", url, strings.NewReader(jsonData))
    req.Header.Add("Content-Type", "application/json")
    req.SetBasicAuth(username, password)
    res, _ := http.DefaultClient.Do(req)

    defer res.Body.Close()
    body, _ := ioutil.ReadAll(res.Body)
    fmt.Println(string(body))
}

term 多条件查问

{
  "query": {
    "bool": {
      "filter": [
        {
          "match_phrase": {"appid": "network"}
        },
        {
          "match_phrase": {"requestid": "bbf60d576b6a08a8c3c1f2cd9"}
        }
      ]
    }
  }
}

参考文章:
https://blog.csdn.net/qq_3785…

https://www.tizi365.com/archi…
https://blog.csdn.net/leo_jk/…

退出移动版