当前位置: 首页 > 工具软件 > Elastic-Go > 使用案例 >

ElasticSearch操作Go

段干靖
2023-12-01

ElasticSearch - Go


Es搜索引擎

  • 优点:容错性好;单点故障时,可以通过复制数据到不同的服务器上达到容错的目的;

  • 使用前提:没有频繁更新(一秒内有大量的更改操作),不需要事务处理,需要对数据进行检索,统计;

  • 存储形式:ES中,存储数据的基本单位就是索引,比如说ES中存储了一些订单系统的销售数据,就因该在ES中创建一个索引(order—index),所有的销售数据就会都写到这个索引里面去,一个索引就像一个数据库,mapping就相当于表的结构定义,定义了什么字段类型等,你往index里添加一行数据就叫做一个document,每一个document有多个filed,每一个filed就代表这个document的一个字段的值。


  • 字段类型: 文档由多个json字段,这个字段跟mysql中的表的字段是类似的。ES中的字段也是有类型的,常用字段类型有:

数值类型(long、integer、short、byte、double、float)

Date 日期类型

boolean布尔类型

Text 支持全文搜索

Keyword 不支持全文搜索,例如:phone这种数据,用一个整体进行匹配就ok了,也不要进行分词处理

Geo 这里主要用于地理信息检索、多边形区域的表达。

  • mapping设计
    Elasticsearch的mapping类似于mysql中的表结构体定义,每个索引都有一个映射的规则,我们可以通过定义索引的映射规则,提前定义好文档的json结构和字段类型,如果没有定义索引的映射规则,ElasticSearch会在写入数据的时候,根据我们写入的数据字段推测出对应的字段类型,相当于自动定义索引的映射规则。

注意:ES的自动映射是很方便的,但是实际业务中,对于关键字段类型,我们都是通常预先定义好,这样可以避免ES自动生成的字段类型不是你想要的类型。

  • 字段存储结构体多为String Json存储 ,读取后通过Json解析即可,对于精确搜索的字段信息采用keyword查询,其他采用ES原生match或term查询。

基本语法

GET /{索引名}/_search
{
 "from" : 0,  // 搜索结果的开始位置
   "size" : 10, // 分页大小,也就是一次返回多少数据
   "_source" :[ ...需要返回的字段数组... ],
 "query" : { ...query子句... },
 "aggs" : { ..aggs子句..  },
 "sort" : { ..sort子句..  }
}
  • 范围查询
GET /{索引名}/_search
{
  "query": {
    "range": {
      "{FIELD}": {
        "gte": 100, 
        "lte": 200
      }
    }
  }
}

{FIELD} - 字段名
gte范围参数 - 等价于>=
lte范围参数 - 等价于 <=
范围参数可以只写一个,例如:仅保留 “gte”: 100, 则代表 FIELD字段 >= 100
gt - 大于 ( > )

gte - 大于且等于 ( >= )

lt - 小于 ( < )

lte - 小于且等于 ( <= )

  • bool组合查询
GET /{索引名}/_search
{
  "query": {
    "bool": { // bool查询
      "must": [], // must条件,类似SQL中的and, 代表必须匹配条件
      "must_not": [], // must_not条件,跟must相反,必须不匹配条件
      "should": [] // should条件,类似SQL中or, 代表匹配其中一个条件
    }
  }
}
  • 排序
GET /{索引名}/_search
{
  "query": {
    ...查询条件....
  },
  "sort": [
    {
      "{Field1}": { // 排序字段1
        "order": "desc" // 排序方向,asc或者desc, 升序和降序
      }
    },
    {
      "{Field2}": { // 排序字段2
        "order": "desc" // 排序方向,asc或者desc, 升序和降序
      }
    }
    ....多个排序字段.....
  ]
}

  • term是代表完全匹配,即不进行分词器分析,文档中必须包含整个搜索的词汇
    match和term的区别是,match查询的时候,elasticsearch会根据你给定的字段提供合适的分析器,而term查询不会有分析器分析的过程,match查询相当于模糊匹配,只包含其中一部分关键词就行

拆分相当于 雷神加速器被拆分为“雷”“神” “加” “速” “器” match 搜索雷、神、加都能够搜索出结果
match查询的结果中一定会有“雷”“神” “加” “速” “器” 字样
term的查询结果就会包含只有“雷”“神” “加” “速” “器” 这个分词结果的数据
match在匹配时会对所查找的关键词进行分词,然后按分词匹配查找,而term会直接对关键词进行查找。一般模糊查找的时候,多用match,而精确查找时可以使用term。

  • 对于.keyword则为不拆分 全文搜索
    Text 与. keyword的区别
    Text:
    会分词,然后进行索引
    支持模糊、精确查询
    不支持聚合
    keyword:
    不进行分词,直接索引
    支持模糊、精确查询
    支持聚合

Elastic-go

go-client参数
elastic.SetURL(url)用来设置ES服务地址,如果是本地,就是127.0.0.1:9200。支持多个地址,用逗号分隔即可。
elastic.SetBasicAuth("user", "secret")这个是基于http base auth 验证机制的账号密码。
elastic.SetGzip(true)启动gzip压缩
elastic.SetHealthcheckInterval(10*time.Second)用来设置监控检查时间间隔
elastic.SetMaxRetries(5)设置请求失败最大重试次数,v7版本以后已被弃用
elastic.SetSniff(false)允许指定弹性是否应该定期检查集群(默认为true)
elastic.SetErrorLog(log.New(os.Stderr, "ELASTIC ", log.LstdFlags)) 设置错误日志输出
elastic.SetInfoLog(log.New(os.Stdout, "", log.LstdFlags)) 设置info日志输出
查询操作
{
"query": {
"bool": {
"must": [
{
"term": {
"Port": "443"
}
}
,
{
"term": {
"State": "established"
}
}
],
"must_not": [
{
"term": {
"RemoteAddr": "0.0.0.0"
}
}
],
"should": [ ]
}
},
"from": 0,
"size": 250,
"sort": [ ],
"aggs": { }
}

Go调用代码
//多条件精确查询
query := elastic.NewBoolQuery()
//排除特定信息用must_not
query  = query.MustNot(elastic.NewTermQuery("RemoteAddr", "0.0.0.0"), elastic.NewTermQuery("RemoteAddr", "127.0.0.1"))
		if ip != "" {
			query = query.Must(elastic.NewTermQuery("IP", ip))
		}
		if value != "" {
			query = query.Must(elastic.NewTermQuery("Port", value))
		}
		if state != "" {
		    //注意term需要小写才能识别 因为分词器会将大写字母转换为小写
			query = query.Must(elastic.NewTermQuery("State", strings.ToLower(state)))
		}
		//查询需要指定size 否则默认为Es查询10条数据,可通过修改ES配置或指定size修改
		res, err := Client.Search("network").Query(query).Size(size).Do(context.Background())
		if err != nil {
			err...
		}
		//判断返回结果数量进行数据处理
		if res.Hits.TotalHits.Value > 0 {
			for _, v := range res.Hits.Hits {
				//v.Source为搜索结果
				json.Unmarshal(v.Source, &temp)
			}
		}
		
//模糊查询
query := elastic.NewBoolQuery()
		if ip != "" {
			query = query.Must(elastic.NewTermQuery("IP", ip))
		}
		if value != "" {
			query = query.Must(elastic.NewWildcardQuery("Name.keyword", value))
		}
		res, err := Client.Search("application").Query(query).Size(size).Do(context.Background())
		if err != nil {
			return nil, err
		}
		if res.Hits.TotalHits.Value > 0 {
			for _, v := range res.Hits.Hits {
				//v.Source为搜索结果
				json.Unmarshal(v.Source, &temp)
			}
		}

/*下面是简单的CURD*/

//创建
func Create(str interface{}, index, id string) error {
	conn := Client.Index()
	_, err := conn.Index(index).Id(id).BodyJson(str).Do(context.Background())
	if err != nil {
		return err
	}
	return nil
}

//删除
func Delete(index, id string) error {
	_, err := Client.Delete().Index(index).
		Id(id).
		Do(context.Background())
	if err != nil {
		return err
	}
	return nil
}

//修改
func Update(str interface{}, index, id string) error {
	_, err := Client.Update().
		Index(index).
		Id(id).
		Doc(str).
		Do(context.Background())
	if err != nil {
		return err
	}
	return nil
}

//查找
func SelectEsToBytes(index, id string) ([]byte, error) {
	//通过id查找
	get1, err := Client.Get().Index(index).Id(id).Do(context.Background())
	if err != nil {
		return nil, err
	}
	if get1.Found {
		return get1.Source, nil
	}
	return get1.Source, errors.New("filed Not Found")
}
 类似资料: