英文:
How to search in elasticsearch with Go filtering results by time frames
问题
我对Go编程还比较新手。
我正在尝试创建一个简单的程序,只做一件事,通过elasticsearch API搜索字符串。
我的问题与我正在使用的"gopkg.in/olivere/elastic.v2"包有关。
这是一个代码示例:
package main
import (
"fmt"
"gopkg.in/olivere/elastic.v2"
"log"
"reflect"
)
type Syslog struct {
Program string
Message string
Timestamp string
}
func main() {
client, err := elastic.NewClient(elastic.SetURL("http://localhost:9200"))
if err != nil {
log.Fatal(err)
}
info, code, err := client.Ping().Do()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Elasticsearch returned with code %d and version %s", code, info.Version.Number)
termQuery := elastic.NewTermQuery("message", "configuration")
searchResult, err := client.Search().
//PostFilter(postFilter).
Index("logstash-*"). // search in index "logstash-*"
Query(&termQuery). // specify the query
Sort("timestamp", true). // sort by "message" field, ascending
From(0).Size(10). // take documents 0-9
Pretty(true). // pretty print request and response JSON
Do() // execute
if err != nil {
log.Fatal(err)
}
fmt.Printf(" Query took %d milliseconds\n", searchResult.TookInMillis)
var ttyp Syslog
for _, item := range searchResult.Each(reflect.TypeOf(ttyp)) {
t := item.(Syslog)
fmt.Printf("Found %s %s %s\n", t.Timestamp, t.Program, t.Message)
}
}
这个代码是可以工作的,但是我真正想要的是通过时间范围来限制搜索。
据我了解,我需要使用FilteredQuery函数。但是我在尝试弄清楚如何创建一个过滤查询时感到困惑。
有一个函数叫做"FilteredQuery",它需要一个查询类型作为输入参数,但是没有函数可以创建查询本身。我只能创建一个所需类型的变量,但它仍然需要像在elasticsearch中要查找的字段和要查找的字符串这样的字段。
对于func (FilteredQuery) Filter
中的Filter变量也是同样的情况。
也许有人已经有一个示例,或者可以指导我正确的方向。
我有一个JSON的示例,如果传递给elastcisearch,可以得到我想要的结果:
"query": {
"filtered": {
"query": {
"query_string": {
"query": "message:\"configuration\"",
"analyze_wildcard": true
}
},
"filter": {
"bool": {
"must": [
{
"range": {
"@timestamp": {
"gte": 1442100154219,
"lte": 1442704954219
}
}
}
],
"must_not": []
}
}
}
}
但是我不知道如何在Go中实现相同的功能。谢谢。
英文:
I am retentively new to programming in Go.
I am trying create a simple program which does only one thing searches string via elasticsearch API.
My question is specific to the "gopkg.in/olivere/elastic.v2" package I am using.
Here is a code sample:
package main
import (
"fmt"
"gopkg.in/olivere/elastic.v2"
"log"
"reflect"
)
type Syslog struct {
Program string
Message string
Timestamp string
}
func main() {
client, err := elastic.NewClient(elastic.SetURL("http://localhost:9200"))
if err != nil {
log.Fatal(err)
}
info, code, err := client.Ping().Do()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Elasticsearch returned with code %d and version %s", code, info.Version.Number)
termQuery := elastic.NewTermQuery("message", "configuration")
searchResult, err := client.Search().
//PostFilter(postFilter).
Index("logstash-*"). // search in index "logstash-*"
Query(&termQuery). // specify the query
Sort("timestamp", true). // sort by "message" field, ascending
From(0).Size(10). // take documents 0-9
Pretty(true). // pretty print request and response JSON
Do() // execute
if err != nil {
log.Fatal(err)
}
fmt.Printf(" Query took %d milliseconds\n", searchResult.TookInMillis)
var ttyp Syslog
for _, item := range searchResult.Each(reflect.TypeOf(ttyp)) {
t := item.(Syslog)
fmt.Printf("Found %s %s %s\n", t.Timestamp, t.Program, t.Message)
}
}
This works, however what I really want is to limit search by time range.
As I understand I need to use FilteredQuery function. But I am lost in attempts to figure out how to create a filtered query.
There is function which created it "FilteredQuery" it requires Query Type as an input parameter but there is no function to create Query itself. I can just create a variable of a required type, still it need to have fields like which filed in elasticsearch to look for and a string to look for.
Same thing goes for the Filter variable in call for func (FilteredQuery) Filter
.
May be someone has already got an example or can point me into the right direction.
I have an example of a JSON which if passed to elastcisearch gets me what I want:
"query": {
"filtered": {
"query": {
"query_string": {
"query": "message:\"configuration\"",
"analyze_wildcard": true
}
},
"filter": {
"bool": {
"must": [
{
"range": {
"@timestamp": {
"gte": 1442100154219,
"lte": 1442704954219
}
}
}
],
"must_not": []
}
}
}
},
But I do not know how to implement the same in Go. Thanks.
答案1
得分: 2
以下是一个产生你想要的结果的示例代码:
package main
import (
"encoding/json"
"fmt"
elastic "gopkg.in/olivere/elastic.v2"
)
func main() {
termQuery := elastic.NewTermQuery("message", "configuration")
timeRangeFilter := elastic.NewRangeFilter("@timestamp").Gte(1442100154219).Lte(1442704954219)
// 不确定这个是否真的有用,我只是把它放在这里以模仿你所期望的结果
boolFilter := elastic.NewBoolFilter().Must(timeRangeFilter)
query := elastic.NewFilteredQuery(termQuery).Filter(boolFilter)
queryBytes, err := json.MarshalIndent(query.Source(), "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(queryBytes))
}
它产生的输出结果是:
{
"filtered": {
"filter": {
"bool": {
"must": {
"range": {
"@timestamp": {
"from": 1442100154219,
"include_lower": true,
"include_upper": true,
"to": 1442704954219
}
}
}
}
},
"query": {
"term": {
"message": "configuration"
}
}
}
}
英文:
See RangeFilter
and FilteredQuery
Here is an example producing the result you want :
package main
import (
"encoding/json"
"fmt"
elastic "gopkg.in/olivere/elastic.v2"
)
func main() {
termQuery := elastic.NewTermQuery("message", "configuration")
timeRangeFilter := elastic.NewRangeFilter("@timestamp").Gte(1442100154219).Lte(1442704954219)
// Not sure this one is really useful, I just put it here to mimic what you said is the expected result
boolFilter := elastic.NewBoolFilter().Must(timeRangeFilter)
query := elastic.NewFilteredQuery(termQuery).Filter(boolFilter)
queryBytes, err := json.MarshalIndent(query.Source(), "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(queryBytes))
}
The output it produces is:
{
"filtered": {
"filter": {
"bool": {
"must": {
"range": {
"@timestamp": {
"from": 1442100154219,
"include_lower": true,
"include_upper": true,
"to": 1442704954219
}
}
}
}
},
"query": {
"term": {
"message": "configuration"
}
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论