i have a sentence to query a group of users by terms (keyword field present uid
) and with a range limit (long filed present unixtime ),the sentence can be executed in Kibana and curl, but when I use golang client(https://github.com/olivere/elastic) to perform the query, after json. Unmarshal(), the sentence is tampered,the range request is abandoned, why? my sentence disobey the json's rule?
package main
import (
"encoding/json"
"fmt"
)
var hot_cache map[string]byte
var followers []string
var prefix = "{\"constant_score\" : {\"filter\" : {\"bool\" : {\"filter\" : {\"range\" : {\"unixtime\" : {\"gte\" : %d, \"lte\" : %d}}}, \"filter\" : {\"terms\" : {\"uid\" : ["
var suffix = "]}}}}}}"
func main() {
tmp := prefix
tmp += "\""
tmp += "123"
tmp += "\""
tmp += suffix
qstr := fmt.Sprintf(tmp, 1, 2)
fmt.Println("raw: ", qstr)
var f interface{}
err := json.Unmarshal([]byte(qstr), &f)
if err != nil {
panic(err)
}
fmt.Println("json: ", f)
}
Output:
raw: {"constant_score" : {"filter" : {"bool" : {"filter" : {"range" : {"unixtimestamp" : {"gte" : 1, "lte" : 2}}}, "filter" : {"terms" : {"uid" : ["123"]}}}}}}
json: map[constant_score:map[filter:map[bool:map[filter:map[terms:map[uid:[123]]]]]]]
any one knows why?
Your "qstr" input JSON string contains the key constant_score.filter.bool.filter
twice, which causes the parser to retain the second value for it.
{
"constant_score": {
"filter": {
"bool": {
"filter": { "range": { "unixtime": { "gte": 1, "lte": 2 } } },
"filter": { "terms": { "uid": [123] } }
}
}
}
}
JSON syntax does not disallow repeated keys; however, it doesn't require that parsers handle them in any special way either, so the vast majority of JSON parsers choose to store the last value of a repeated key in an object, and go's unmarshaler is no different.
Here's an example - consider the following valid JSON string:
{"a":1,"a":2}
Suppose you deserialized this document into an object (e.g. map, dictionary, k/v store, etc). Since keys are unique in such data structures, what value should be stored for they key "a", 1 or 2?
// JavaScript
JSON.parse('{"a":1,"a":2}'); // => {a: 2}
# Ruby
JSON.parse('{"a":1,"a":2}') # => {"a" => 2}
# Python
json.loads('{"a":1,"a":2}') # => {u'a': 2}
// Go
var obj interface{}
err := json.Unmarshal([]byte(`{"a":1,"a":2}`), &obj)
if err != nil {
panic(err)
}
fmt.Printf("%#v
", obj)
// map[string]interface {}{"a":2}