【问题标题】:How to handle nested structures in golang for Elasticsearch replies?如何在 golang 中处理 Elasticsearch 回复的嵌套结构?
【发布时间】:2020-12-19 18:51:18
【问题描述】:

我有一个用 Go 编写的 API 服务,使用 gin-gonic,它由 Elasticsearch 服务支持。查询命中 API,API 服务器查询 Elasticsearch,Elasticsearch 将搜索结果回复给 API,API 将结果返回给启动流程的一方。所有这些都“有效”,端到端,但是有一个问题。

在 Elasticsearch 中,我有 20 个索引——每个索引都有数千个文档。当我使用 go-elasticsearch 通过 gin-gonic 查询 Elasticsearch 中的一个索引时,我得到了一个 Elasticsearch 结果,它被解组到这些结构中:

type esResult struct {
        Took     int        `json:"took"`
        Timedout bool       `json:"timed_out"`
        Shards   jsonShards `json:"_shards"`
        Hits     jsonHits   `json:"hits"`
}

type jsonShards struct {
        Total      int `json:"total"`
        Successful int `json:"successful"`
        Skipped    int `json:"skipped"`
        Failed     int `json:"failed"`
}

type jsonHits struct {
        Total    jsonTotal     `json:"total"`
        Maxscore float64       `json:"max_score"`
        Hitlist  []jsonHitlist `json:"hits"`
}

type jsonHitlist struct {
        Index string  `json:"_index"`
        Type  string  `json:"_type"`
        ID    string  `json:"_id"`
        Score float64 `json:"_score"`
        Source customForIndex `json:"_source"`
        //      Source []byte `json:"_source"`
}

我的问题是,上面显示为“customForIndex”类型结构的 esResult.Hits.Hitlist.Source 字段根据我查询的索引而有所不同。

我想做的是这样的:

                var esres esResult
                err := json.Unmarshal(resp, &esres)

如果我使用 customForIndex 效果很好,但如果我将 Source 设置为 string 或 []byte(以便我可以单独解组 Source),它似乎不起作用。

我知道的解决方法很糟糕,它是定义重复的结构(一组,每个索引),但这很糟糕,因为它会导致许多 esResult 结构、许多 Hits 结构等等,它们是所有重复。

那么,我如何解组 Elasticsearch 回复,以便获得回复的自定义部分?

换一种说法,如果我从 Elasticsearch 获取回复,直接传递给 API 服务器(进而传递给客户端),不做任何处理,那么它包含了各种(对客户端)无关的 Elasticsearch 信息。所以我的计划是去掉所有这些,只在 Elasticsearch 回复中包含来自 Source 对象的数据。但是如果我解组esResult,esResult本身在其他索引上是无效的,因为子结构不同。

想法?任何帮助,将不胜感激。基本上我的问题与在 golang 中解组嵌套结构有关,并且恰好出现在 Elasticsearch 用例中,因为大多数(但不是全部)结构在索引之间是重复的。

【问题讨论】:

    标签: go elasticsearch struct nested go-gin


    【解决方案1】:

    我正在阅读您的答案,我记得当我与弹性战斗只返回我需要的东西时。

    真的不知道你是怎么查询的(如果你能分享一些代码,那就太好了)

    但是,就我而言,a 做了以下事情。

             "aggs": {
                "top_values": {
                  "terms": {
                    "field": "data.field_group.keyword"
                  },
                  "aggs": {
                    "top_field_hits": {
                      "top_hits": {
                        "_source": {
                          "includes": [ "data.field1", "data.field2", "data.field3", "data.field4"]
                        }
                      }
                    }
                  }
                }
              }
    

    然后阅读回复,阅读结果以:

    for _, hit := range values["aggregations"].(map[string]interface{})["top_values"].(map[string]interface{})["buckets"].([]interface{})
    

    在这个“FOR”语句中,我对包含“hit”的结构进行了 Marshall,然后对 MY 结构进行了 unmarshal。

    var totalValue MyStruct
    marshalTotal, _ := json.Marshal(hit)
    _ = json.Unmarshal(marshalTotal, &totalValue)
    

    您需要在结构中使用与 elastic 结果相同的标签名称。

    MyProperty string `json:"elasticNameField"`
    

    另一方面,也许您可​​以使用 [Olivera] 1 库,根据我的经验,它是一个很好的库,但我发现查询的响应时间有所不同。

    我希望您可以使用此信息来解决您的问题。

    问候,

    【讨论】:

      猜你喜欢
      • 2016-03-10
      • 1970-01-01
      • 1970-01-01
      • 2021-08-08
      • 2014-03-25
      • 2021-12-24
      • 1970-01-01
      • 2014-07-31
      • 1970-01-01
      相关资源
      最近更新 更多