Elasticsearch update script - 'noop' flushes entire script - elasticsearch

I want to update 2 fields in a document in a single update request, using an inline painless script:
{
"script" : {
"inline": "ctx._source.counter1 ++ ; ctx._source.counter2 == 0 ? ctx.op = 'noop' : ctx._source.counter2 ++"}
}
Problem is - if the condition is met and ctx.op = 'noop' then the first part of the script (ctx._source.counter1 ++ ;) is also not being executed.
How would u recommend I should do this?
I can split the operation into 2 update requests which will double my db calls (but maybe a 'noop' call is extremely fast).
I also tried to swap the 2 parts of script (the conditional first , the increment second) - but then I'm getting a compilation error:
"script_stack": [
" ctx._source. ...",
" ^---- HERE"
],
"script": " ctx._source.counter2 > 0 ? ctx.op = 'noop' : ctx._source.counter2++ ; ctx._source.counter1++ ",
"lang": "painless",
"caused_by": {
"type": "illegal_argument_exception",
"reason": "Not a statement."
}
Any ideas?
Thanks

Related

Elastic: mismatched input '-'

I'm running this code and I'm getting this error and I just can't figure out what's wrong with it:
POST /_sql/translate
{
"query": "SELECT duracao, elementoRede, hostname, ingest_time FROM reta-* WHERE duracao > 0 ORDER BY duracao DESC LIMIT 10",
"fetch_size": 100
}
You need to escape the special character, try this
POST /_sql/translate
{
"query": "SELECT duracao, elementoRede, hostname, ingest_time FROM \"reta-*\" WHERE duracao > 0 ORDER BY duracao DESC LIMIT 10",
"fetch_size": 100
}

TextMate Grammar - Problem with `end` expression

I'm having huge problems with the end portion of a regex in TextMate:
It looks like end becomes the part of the pattern that's returned between begin and end
Trying to apply multiple endings with one negative lookbehind proves unsuccessful
Here is an example code:
property_name: {
test1: [1, 50, 5000]
test2: something ;;
test3: [
1,
50,
5000
]
test4: "string"
test5: [
"text",
"text2"
]
test6: something2
test7: something3
}
I'm using the following code:
"begin": "\\b([a-z_]+):",
"beginCaptures": {
"1": {
"name" : "parameter.name"
}
}
"end": "(?<!,)\\n(?!\\])",
"patterns": [
{
"name": "parameter.value",
"match": "(.+)"
}
]
My logic for the end regular expression is to consider it ended if there's a new line but only if it's not preceded by a comma (list of values in an array) or followed by a closing square bracket (last value in an array).
Unfortunately it's not working as expected.
What I would like to achieve is that all property_name# and test are matched as parameter.name and the values are matched as parameter.value apart from ;;

Painless Scripting Kibana 6.4.2 not matching using matcher, but matches using expression conditional

Hello I'm trying to take a substring of a log message using regex in kibana scripted fields. I've run into an interesting scenario that doesn't add up. I converted the message field to a keyword so I could do scripted field operations on it.
When I match with a conditional such as:
if (doc['message'].value =~ /(\b(?:\d{1,3}\.){3}\d{1,3}\b)/) {
return "match"
} else {
return "no match"
}
This will match the ip and return correctly that there is an ip in the message. However, whenever I try to do the matcher function which splits the matched text into substrings it doesn't find any matches.
Following the guide on Elastic's documentation for doing this located here:
https://www.elastic.co/blog/using-painless-kibana-scripted-fields
This is the example script they give to match the first octet of an ip in a log message. However, this returns no matches when indeed there is ip addresses in the log message. I can't even match just text characters no matter what I do it returns 0 matches.
I have enabled rexex in the elasticsearch.yml in my cluster as well.
def m = /^([0-9]+)\..*$/.matcher(doc['message'].value);
if ( m.matches() ) {
return Integer.parseInt(m.group(1))
} else {
return m.matches() + " - " + doc['message'].value;
}
This returns 0 matches. Even if I use the same expression used for the conditional:
/(\b(?:\d{1,3}.){3}\d{1,3}\b)/
the matcher will still return false.
Any idea what I'm doing wrong here according to the documentation this should work.
I tried using subs-strings when the value exists in the if conditional but there is to many variations between the log messages. I also don't see a way to split and look through the list of outputs to pick the one with ip if I just use conditional for the scripted field.
Any idea on how to solve this:
Here is a example of that is returned form
def m = /^([0-9]+)\..*$/.matcher(doc['message'].value);
if ( m.matches() ) {
return Integer.parseInt(m.group(1))
} else {
return m.matches() + " - " + doc['message'].value;
}
The funny part is they all return false and this is essentially just looking for numbers with . and I've tried all kinds of regex combinations with no luck.
[
{
"_id": "VRYK_2kB0_nHZ_3qyRwt",
"Source-IP": [
"false - #Version: 1.0"
]
},
{
"_id": "VhYK_2kB0_nHZ_3qyRwt",
"Source-IP": [
"false - 2019-02-17 00:34:11 127.0.0.1 GET /status/web - 8611 - 127.0.0.1 ELB-HealthChecker/2.0 - 200 0 0 31"
]
},
{
"_id": "VxYK_2kB0_nHZ_3qyRwt",
"Source-IP": [
"false - #Software: Microsoft Internet Information Services 10.0"
]
},
{
"_id": "WBYK_2kB0_nHZ_3qyRwt",
"Source-IP": [
"false - #Date: 2019-03-26 00:00:08"
]
},
{
"_id": "WRYK_2kB0_nHZ_3qyRwt",
"Source-IP": [
127.0.0.1 ELB-HealthChecker/2.0 - 200 0 0 15"
]
},
{
ended up being the following:
if (doc["message"].value != null) {
def m = /(\b(?:\d{1,3}\.){3}\d{1,3}\b)/.matcher(doc["message"].value);
if (m.find()) { return m.group(1) }
else { return "no match" }
}
else { return "NULL"}

elasticsearch: using wildcards for integer values

I would like to find all objects which have a year value which starts with 20... so I would like to search for 20*, where * is a wild card.
I tries something like
'match_phrase_prefix': { 'year': { 'query': '20*', 'max_expansions': 50}}
but I guess this only works for strings. How would I do this for integers?
EDIT: I found a solution... its not pretty but it works
year_query = '20'
if len(str(year_query)) < 4:
try:
low_year, high_year = extend_year(int(year_query))
filter_list.append({"range": {"year": {"gte": low_year, "lte": high_year}}})
except ValueError:
print "Not a valid input for year"
pass
else:
for year in year_query.split(','):
if '-' in year:
year_range = year.split('-')
high_year = year_range[1].strip()
if len(high_year) < 4:
low_year, high_year = extend_year(high_year)
try:
filter_list.append({"range" : {"year" : {"gte" : int(year_range[0].strip()),"lte" : int(high_year),"format": "yyyy"}}})
except ValueError:
print "Not a valid input for year"
pass
else:
try:
filter_list.append({ "match": {"year": int(year.strip()) }})
except ValueError:
print "Not a valid input for year"
pass
with the function
def extend_year(input_year):
length = len(str(input_year))
if length == 4:
return input_year, 0
elif length == 3:
return input_year*10, int(str(input_year) + '9')
elif length == 2:
return input_year*100, int(str(input_year) + '99')
elif length == 1:
return input_year*1000, int(str(input_year) + '999')
elif length == 0:
return 0, 9999
else:
return input_year, 0
if anybody can come up with a better solution please let me know
This should work
'range': { 'year': { 'gte': 2000, 'max_expansions': 50}}

Select by for a two-dimensional hash

I have this hash
- "title" : "The Today Show",
- "category; "Show",
- "channel-name": "CNBC",
- "scheduling" =>
{ "start" : "7am", "stop" : "9am"},
{ "start" : "10am", "stop" : "11am"},
{ "start" : "11am", "stop": "12am"}
- "title" : "How I met your mother",
- "category; "Show",
- "channel-name": "CBS",
- "scheduling" =>
{ "start" : "7pm", "stop" : "9pm"},
{ "start" : "10pm", "stop" : "12pm"},
{ "start" : "11am", "stop": "12am"}
I need to "select" only programs which have at least one schedule beetween "7pm"-"9pm"
I tried this, but it isn't working
programs.select_by{|p|
p.scheduling.each{|ps|
ps.start <= "7pm" && ps.stop <= "9pm"
}
}
PS: I used a pseudo-code for the date-comparison just to make this code more readable :)
Try this
programs.select do |p|
p.scheduling.any? do |ps|
ps.start >= "7pm" && ps.stop <= "9pm"
end
end

Resources