ElasticSearch Date Range Aggregation over different fields - json

I want to be able to fetch documents over a certain date range as provided by the user and the display the document to be viewed. The query that i have currently constructed looks like this :
query
{
"aggs": {
"range": {
"date_range": {
"field": "metadata.o2r.temporal.begin",
"ranges": [
{ "from": "2017-03-30T12:35:41.142Z", "to": "2017-08-02T22:00:00.000Z", "key": "quarter_01" }
],
"keyed": true
}
}
}
}
'
The temporal part of the json documents that i am trying to fetch are like the following:
JSON
"temporal": {
"begin": "2017-08-01T22:00:00.000Z",
"end": "2017-03-30T12:35:41.142Z"
},
Currently i can either query "begin" or "end" but i want to be able to modify the query in such a way that begin becomes a value for "from" and end becomes a values for "to". The catch is here that i do not want my original JSON to be modified.
Updated Query
curl -XGET 'localhost:9201/test/_search?size=0&pretty' -H 'Content-Type: application/json' -d'
> {
> "query": {
> "bool": {
> "must": [
> {
> "range": {
> "metadata.o2r.temporal.begin": {
> "from": "2016-01-01T12:35:41.142Z"
> }
> }
> } ,
> {
> "range": {
> "metadata.o2r.temporal.end": {
> "to": "2016-12-30T22:00:00.000Z"
> }
> }
> }
> ]
> }
> }
> }
> '
Response
{
"took" : 1678,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 0.0,
"hits" : [ ]
}
}

This might help you
{
"query": {
"bool": {
"must": [
{
"range": {
"metadata.o2r.temporal.begin": {
"from": "2017-03-30T12:35:41.142Z"
}
}
} ,
{
"range": {
"metadata.o2r.temporal.end": {
"to": "2017-08-02T22:00:00.000Z"
}
}
}
]
}
}
}

Related

JSON for Elasticsearch: three fields and three queries

Is there any way to write by query_string this query?
(field_one : "word_one" OR "word_two" OR "word_three") AND (field_one
: "word_four" OR "word_five" OR "word_six") AND (field_two :
"word_seven" OR "word_eigth" OR "word_nine")
Like this, but with three fields and three queries?
"query": {
"bool": {
"must": [
{
"query_string": {
"fields": [
"my_search_field"
],
"query": "my_search_query"
}
}
]
}
}
I tried to write it using filter:
"filter": [
{
"bool": {
"filter": [
{
"bool": {
"should": should_phrases_a, #words by field_one
"minimum_should_match": 1
}
},
{
"bool": {
"should": should_phrases_b, #words by field_one
"minimum_should_match": 1
}
},
{
"bool": {
"should": should_phrases_c, #words by field_two
"minimum_should_match": 1
}
}
]
}
}
]
Where should_phases_a/b/c look like list of:
{"bool": {"should": [{
"match_phrase": {
"field_one": "word_one"
}
}
],
"minimum_should_match": 1
}
}
But it didn't worked for me. It was good only with one_field intersection (without part with should_phrases_c):
(field_one : "word_one" OR "word_two" OR "word_three") AND (field_one
: "word_four" OR "word_five" OR "word_six")
You can specify fields in query
Query
{
"query": {
"query_string": {
"query": """
(field_one:word_one OR word_two OR word_three)
AND (field_one:word_four OR word_five OR word_six)
AND (field_two:word_seven OR word_eigth OR word_nine)
"""
}
}
}

Filter date range "day before yesterday" in json query for logz.io api (elastic search)

Context: Querying logz.io through the API.
The following query returns results for yesterday
{
"size":10000,
"query" : {
"bool" : {
"must" : [
{ "range": { "#timestamp": { "gte": "now-1d/d", "lt": "now/d" } } }
]
}
}
}
I was hoping this one to return results for the day before yesterday
{
"size":10000,
"query" : {
"bool" : {
"must" : [
{ "range": { "#timestamp": { "gte": "now-2d/d", "lt": "now-1/d" } } }
]
}
}
}
But it doesn't return anything.
What am I missing?
You're just missing a d in the lt part
{
"size":10000,
"query" : {
"bool" : {
"must" : [
{ "range": { "#timestamp": { "gte": "now-2d/d", "lt": "now-1d/d" } } }
^
|
here
]
}
}
}

expected [END_OBJECT] but got [FIELD_NAME], possibly too many query clauses error in kibana

when I am trying to comprise a compound bool query that has a fuzzy must requirement and several should reqs with one being a wildcard, I run into this error message. So far, no alterations to the syntax have helped me to resolve this issue.
The query:
{
"query": {
"bool": {
"must": {
"fuzzy": {
"message": "<fuzzy string>",
"fuzziness": "auto"
}
},
"should": [
{ "query": { "message": "<string>" } },
{ "query": { "message": "<string>" } },
{ "wildcard":
{
"query": { "message": "<partial string*>"}
}
}
],
"minimum_should_match": "50%"
}
}
}
The text inside <> is replaced with my searched string.
You need to replace query with match in your bool/should clause:
> { "query": {
> "bool": {
> "must": {
> "fuzzy": {
> "message": "<fuzzy string>",
> "fuzziness": "auto"
> }
> },
> "should": [
> {"match": {"message": "<string>"}}, <-- here
> {"match": {"message": "<string>"}}, <-- and here
> {"wildcard": {"query": {"message": "<partial string*>"}}}
> ],
> "minimum_should_match": "50%"
> } } }

Elasticsearch bucket aggregation using concatenated parameter

I'm using Elasticsearch API and the schema of the document as follow
{
name: "",
born_year: "",
born_month: "",
born_day: "",
book_type: "",
price: <some number>,
country: ""
}
Now what I need is to get the document count per each name where born before 1995 (born_year + born_month + born_day < "20051220"). How can i achieve?
I tried this:
{
"query": {
"query_string": {
"query": "country:\"SL\""
}
},
"size": 0,
"aggs": {
"total": {
"terms": {
"field": "name"
}
}
}
}
But I have no idea how can I add filter for the birthday.
As mentioned by #val, you need to add a real date field that you can easily add by concatenating these three fields at creation time.
But how you filter based on date range, there are two ways and both of them will return different result sets
Now the level of filtering is your choice.
You mentioned querying on country field. But you have not mentioned at what level you want to filter on date range. I will give you queries for both the cases.
Mappings- assuming you create a date field.
{
name:"",
born_year:"",
born_month:"",
born_day:"",
book_type:"",
price:<some number>,
country:"",
date : ""
}
Case - 1) Filtering date range for name aggregations only, here documents count will not be effected by the date range filter
{
"query": {
"query_string": {
"query": "country:\"SL\""
}
},
"aggs": {
"total": {
"filter": {
"range": {
"date": {
"gte": "your_date_mx",
"lte": "your_date_min"
}
}
},
"aggs": {
"NAME": {
"terms": {
"field": "name",
"size": 10
}
}
}
}
}
}
Case 2) In this case both your documents count and aggregation will be filtered for date range as we add date range filter at query level.
{
"query": {
"query_string": {
"query": "country:\"SL\""
},
"bool": {
"must": [
{
"range": {
"date": {
"gte": "your_date_mx",
"lte": "your_date_mic"
}
}
}
]
}
},
"aggs": {
"toal": {
"terms": {
"field": "name",
"size": 10
}
}
}
}
So adding a filter to aggregation will effect only aggs count.
Edit -
Approach1) with groovy script try to concatinate the string and parse it to integer and then compare with your input date.
{
"query": {
"bool": {
"must": [
{}
],
"filter": {
"script": {
"script": {
"inline": "(doc['year'].value + doc['month'].value + doc['date'].value).toInteger() > 19910701",
"params": {
"param1": 19911122
}
}
}
}
}
}
}
Make sure when indexing index date(or month) with single digit like 6 as 06
2) Approach 2 - parse the string the exact date(preferred)
{
"query": {
"bool": {
"must": [
{}
],
"filter": {
"script": {
"script": {
"inline": "Date.parse('dd-MM-yyyy',doc['date'].value +'-'+ doc['month'].value +'-'+ doc['year'].value).format('dd-MM-yyyy') > param1",
"params": {
"param1": "04-05-1991"
}
}
}
}
}
}
}
Second approach is much better approach as you don't have to worry about the maintaing the string for each field(date, month, day) to later parse to proper int for comparing.

Conversion from sql to elastic search query

I want to convet the foll. sql query to elastic json query
select count(distinct(fk_id)),city_id from table
where status1 != "xyz" and satus2 = "abc" and
cr_date >="date1" and cr_date<="date2" group by city_id
Also is there any way of writing nested queries in elastic.
select * from table where status in (select status from table2)
The first query can be translated like this in the Elasticsearch query DSL:
curl -XPOST localhost:9200/table/_search -d '{
"size": 0,
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"term": {
"status2": "abc"
}
},
{
"range": {
"cr_date": {
"gt": "date1", <--- don't forget to change the date
"lt": "date2" <--- don't forget to change the date
}
}
}
],
"must_not": [
{
"term": {
"status1": "xyz"
}
}
]
}
}
}
},
"aggs": {
"by_cities": {
"terms": {
"field": "city_id"
},
"aggs": {
"fk_count": {
"cardinality": {
"field": "fk_id"
}
}
}
}
}
}'
Using Sql API In Elastic search, we can write queries and also we can translate them to elastic query
POST /_sql/translate
{
"query": "SELECT * FROM customer where address.Street='JanaChaitanya Layout' and Name='Pavan Kumar'"
}
Response for this is
{
"size" : 1000,
"query" : {
"bool" : {
"must" : [
{
"term" : {
"address.Street.keyword" : {
"value" : "JanaChaitanya Layout",
"boost" : 1.0
}
}
},
{
"term" : {
"Name.keyword" : {
"value" : "Pavan Kumar",
"boost" : 1.0
}
}
}
],
"adjust_pure_negative" : true,
"boost" : 1.0
}
},
"_source" : {
"includes" : [
"Name",
"address.Area",
"address.Street"
],
"excludes" : [ ]
},
"docvalue_fields" : [
{
"field" : "Age"
}
],
"sort" : [
{
"_doc" : {
"order" : "asc"
}
}
]
}
Now we can use this result to query elastic search
For further details please go through this article
https://xyzcoder.github.io/elasticsearch/2019/06/25/making-use-of-sql-rest-api-in-elastic-search-to-write-queries-easily.html