{"id":15152461,"url":"https://github.com/leakix/yql-elastic","last_synced_at":"2025-10-24T08:31:12.334Z","repository":{"id":48956325,"uuid":"372968624","full_name":"LeakIX/yql-elastic","owner":"LeakIX","description":"Why another query language for Elastic ?","archived":false,"fork":false,"pushed_at":"2021-09-20T08:27:18.000Z","size":30,"stargazers_count":6,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-07T17:38:32.020Z","etag":null,"topics":["elasticsearch","golang","query-language"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LeakIX.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-06-01T21:45:04.000Z","updated_at":"2024-11-30T16:56:12.000Z","dependencies_parsed_at":"2022-09-02T03:22:09.197Z","dependency_job_id":null,"html_url":"https://github.com/LeakIX/yql-elastic","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LeakIX%2Fyql-elastic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LeakIX%2Fyql-elastic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LeakIX%2Fyql-elastic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LeakIX%2Fyql-elastic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LeakIX","download_url":"https://codeload.github.com/LeakIX/yql-elastic/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":237937810,"owners_count":19390543,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["elasticsearch","golang","query-language"],"created_at":"2024-09-26T16:01:58.568Z","updated_at":"2025-10-24T08:31:12.051Z","avatar_url":"https://github.com/LeakIX.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# YQL Elastic\n\nYQL Elastic ( aka Why QL ) is a golang library implementing its own query language to construct Bool based Elasticsearch queries.\n\nIt is based on the Lucene query language but doesn't implement duplicate operators like `AND`, `OR`, `NOT` ect...\n\nIt is useful when Elasticsearch's query syntax shows its limit ( eg [Nested documents](https://www.elastic.co/guide/en/elasticsearch/reference/current/nested.html) ).\n\n## Features\n\n- Parse Lucene like query to [Olivere's Elasticsearch Client](https://gopkg.in/olivere/elastic.v7) [Query](https://pkg.go.dev/gopkg.in/olivere/elastic.v7#Query) interface.\n- Supports groups\n- Supports field remapping\n- Supports nested fields\n\n\n## Lexical declarations :\n\n- Any term or group of term following `+` is a `Must` condition.\n- Any term or group of term following `-` is a `MustNot` condition.\n- Any term or group of term without preceding operator is a `Should` condition.\n- A group is query inside delimiting `()`\n- Groups can have sub-groups\n- A term can be a single word \n- A term can be a phrase between quote \n- A term can be a field, prefixed by `:` with or without a (single word or phrase) as value\n- Any field having a `\u003e` after its `:` is a greater range condition.\n- Any field having a `\u003c` after its `:` is a lower range condition.\n- Any field having a `=` after its `:` is a precise match condition.\n- Any field having a `~` after its `:` is a regex condition.\n\n\n## Quirks\n\n- Field groups (eg `field:(test1 -test2)`) is directly passed to SimpleQueryString. This means `AND` `OR` \n  and other lucene operators are active for this field.\n\n## Build tester\n\nYou need the [Go tools](https://github.com/golang/tools#downloadinstall) installed to re-generate the `*_string.go`\nfiles if necessary.\n\n```shell\n$ go generate\n$ go build ./cmd/testyql\n$ ./testyql \"+(test test2 test3) wrong'test'  +'test phrase phrase' --((-test4  +test34:\\\"323\\\" test14 test453) -(a:test +b:3333)) (test:)\"\n{\"bool\":{\"must\":[{\"bool\":{\"should\":[{\"multi_match\":{\"fields\":[\"default_field\"],\"query\":\"test\"}},{\"multi_match\":{\"fields\":[\"default_field\"],\"query\":\"test2\"}},{\"multi_match\":{\"fields\":[\"default_field\"],\"query\":\"test3\"}}]}},{\"multi_match\":{\"fields\":[\"default_field\"],\"query\":\"'test phrase phrase'\"}}],\"must_not\":{\"bool\":{\"must_not\":{\"bool\":{\"must\":{\"multi_match\":{\"fields\":[\"b\"],\"query\":\"3333\"}},\"should\":{\"multi_match\":{\"fields\":[\"a\"],\"query\":\"test\"}}}},\"should\":{\"bool\":{\"must\":{\"multi_match\":{\"fields\":[\"test34\"],\"query\":\"\\\"323\\\"\"}},\"must_not\":{\"multi_match\":{\"fields\":[\"default_field\"],\"query\":\"test4\"}},\"should\":[{\"multi_match\":{\"fields\":[\"default_field\"],\"query\":\"test14\"}},{\"multi_match\":{\"fields\":[\"default_field\"],\"query\":\"test453\"}}]}}}},\"should\":[{\"multi_match\":{\"fields\":[\"default_field\"],\"query\":\"wrong'test'\"}},{\"bool\":{\"should\":{\"multi_match\":{\"fields\":[\"test\"],\"query\":\"\"}}}}]}}\n```\n\n## Examples :\n\n### Valid queries\n\n- `test`\n- `+(test test2 test3) e'test'  +'super phrase' --((-test4  +test:\"323\" e qe) -(a:test +b:ewe)) (test:)`\n- `+(text field1:(+test -test2) -field2:text2 +test.id:43`\n\n### Usage\n\nFrom `cmd/testysql/main.go`:\n\n```golang\npackage main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"github.com/LeakIX/yql-elastic\"\n\t\"log\"\n\t\"os\"\n)\n\nelasticQuery, err := yql_elastic.Parse(os.Args[1],\n    yql_elastic.WithDefaultFields([]string{\"events.hostname\",\"events.summary\"}),\n    yql_elastic.WithNestedPaths([]string{\"events\"}),\n    yql_elastic.WithFieldMapping(map[string]string{\n        \"host\":\"events.host\",\n        \"port\":\"open_ports\",\n        \"fingerprint\":\"fingerprints\",\n        \"ssl\":\"events.ssl\",\n    }),\n)\nif err != nil {\n    log.Fatal(err)\n}\nquerySource, err := elasticQuery.Source()\nif err != nil {\n    log.Fatal(err)\n}\nquerySourceJson, err := json.Marshal(querySource)\nif err != nil {\n    log.Fatal(err)\n}\nfmt.Println(string(querySourceJson))\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleakix%2Fyql-elastic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleakix%2Fyql-elastic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleakix%2Fyql-elastic/lists"}