I have an API service written in Go, using gin-gonic, which is backed by an Elasticsearch service. Queries hit the API, the API server queries Elasticsearch, Elasticsearch replies with the search results to the API, and the API serves the results back to the party that started the process. All of it "works", end-to-end, but there is a problem.
In Elasticsearch, I have 20 indexes -- each index has thousands of documents. When I use go-elasticsearch to query one of the indexes in Elasticsearch, via gin-gonic, I get an Elasticsearch result back, which gets unmarshal'd into these structs:
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"`
}
My problem is that when the esResult.Hits.Hitlist.Source field, shown above as a struct of type 'customForIndex', differs depending on which Index I query.
What I'd like to do, is this:
var esres esResult
err := json.Unmarshal(resp, &esres)
That works fine, if I use customForIndex, but if I set Source to string or []byte (so that I can unmarshal Source separately), it does not seem to work.
The workaround, which I'm aware is awful, is to define duplicate structures (one set, per index), but that's awful, as it would result in many esResult structures, many Hits structures, and so on, which are all duplicates.
So how do I unmarshal Elasticsearch replies, so that I can get at the custom part of the reply?
Said another way, if I take the reply from Elasticsearch and pass it directly to the API server (and thus to the client), without any processing, then it includes all sorts of irrelevant (to the client) Elasticsearch information. So my plan was to strip all that out, and only include the data from the Source object in the Elasticsearch reply. But if I unmarshal esResult, esResult itself is invalid on other indexes, because the child struct is different.
Thoughts? Any help would be appreciated. Basically my question relates to unmarshaling nested structures in golang and just happens to show up in Elasticsearch use cases because most (but not all) of the structures are duplicative across indexes.