Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix filters for complex painless scripted fields #9171

Merged
merged 4 commits into from
Nov 29, 2016

Conversation

Bargs
Copy link
Contributor

@Bargs Bargs commented Nov 21, 2016

Painless scripted fields that consisted of more than a single expression
would break when the user attempted to filter on them in Discover or
Visualize because of the naive way we were building them. We now wrap
the user's script in a lambda so that it can be as complex at they need
it to be. The only special exception is that the user cannot define
named functions since those cannot go inside a Painless lambda.

Note Make sure to use a recent build of ES when testing, you'll get an error if the ES PR referenced below isn't included in your build. ESVM's build is currently out of date.

Fixes #9024
Related elastic/elasticsearch#21635

Painless scripted fields that consisted of more than a single expression
would break when the user attempted to filter on them in Discover or
Visualize because of the naive way we were building them. We now wrap
the user's script in a lambda so that it can be as complex at they need
it to be. The only special exception is that the user cannot define
named functions since those cannot go inside a Painless lambda.

Fixes elastic#9024
Related elastic/elasticsearch#21635
@Bargs
Copy link
Contributor Author

Bargs commented Nov 21, 2016

@nik9000 any chance you could glance over the painless I wrote in here and make sure I'm not doing anything stupid? Things seem to be working but I'm not a painless guru.

Copy link
Member

@nik9000 nik9000 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to me. I left a super minor thing.

}).join(' && ');

// We must wrap painless scripts in a lambda in case they're more than a simple expression
if (field.lang === 'painless') {
const comparators = `boolean gt(Supplier s, def v) {return s.get() > v;}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically you don't need a ; before a } in painless ever. Mad lexer hax.

Anyway, maybe only emit the one of these comparators that you need? It doesn't seem worth it to go through the trouble of building these methods if you aren't going to use them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, thanks for the quick feedback!

Bargs added a commit to Bargs/kibana that referenced this pull request Nov 21, 2016
We made a mistake in opening up Kibana scripted fields to any and all
langs enabled in Elasticsearch. Kibana needs to do some magic to get
certain scripted field features to work
(elastic#9171) and we can't commit to
supporting anything beyond expression and painless scripts. On top of
that, the other languages are being deprecated in ES 6.0 anyway. This commit
makes that stance explicit by disallowing anything other than those two
choices.
Bargs added a commit to Bargs/kibana that referenced this pull request Nov 22, 2016
We made a mistake in opening up Kibana scripted fields to any and all
langs enabled in Elasticsearch. Kibana needs to do some magic to get
certain scripted field features to work
(elastic#9171) and we can't commit to
supporting anything beyond expression and painless scripts. On top of
that, the other languages are being deprecated in ES 6.0 anyway. This commit
makes that stance explicit by disallowing anything other than those two
choices.
Bargs added a commit to Bargs/kibana that referenced this pull request Nov 22, 2016
We made a mistake in opening up Kibana scripted fields to any and all
langs enabled in Elasticsearch. Kibana needs to do some magic to get
certain scripted field features to work
(elastic#9171) and we can't commit to
supporting anything beyond expression and painless scripts. On top of
that, the other languages are being removed in ES 6.0 anyway. This commit
makes that stance explicit by disallowing anything other than those two
choices.
@tbragin tbragin added the Feature:Scripted Fields Scripted fields features label Nov 22, 2016
@tbragin
Copy link
Contributor

tbragin commented Nov 22, 2016

@Bargs I tried out a couple of scripts

Filtering works for this script

def m = /^([0-9]+)\..*$/.matcher(doc['clientip.keyword'].value);
if ( m.matches() ) {
   return Integer.parseInt(m.group(1))
} else {
   return 0
}

But not for this

def path = doc['url.keyword'].value;
if (path != null) {
    int lastSlashIndex = path.lastIndexOf('/');
    if (lastSlashIndex > 0) {
	return path.substring(lastSlashIndex+1)
    }
}

screen shot 2016-11-21 at 4 47 42 pm

Resulting filter copied from UI

{
  "script": {
    "script": {
      "inline": "boolean compare(Supplier s, def v) {return s.get() == v;}\n                        compare(() -> { def path = doc['url.keyword'].value;\nif (path != null) {\n    int lastSlashIndex = path.lastIndexOf('/');\n    if (lastSlashIndex > 0) {\n\treturn path.substring(lastSlashIndex+1)\n    }\n} }, params.value);",
      "lang": "painless",
      "params": {
        "value": "profile"
      }
    }
  }
}

@nik9000
Copy link
Member

nik9000 commented Nov 22, 2016

What about

def path = doc['url.keyword'].value;
if (path != null) {
    int lastSlashIndex = path.lastIndexOf('/');
    if (lastSlashIndex > 0) {
	return path.substring(lastSlashIndex+1)
    }
}
return null

?

@tbragin
Copy link
Contributor

tbragin commented Nov 22, 2016

@nik9000 That works! So is it paramount that a well-defined return value is provided for every execution path?

@nik9000
Copy link
Member

nik9000 commented Nov 22, 2016

Yeah, at least it is in methods. Maybe @jdconrad can talk about that? I
don't know why it is ok for the main function and not all functions in
general.

On Mon, Nov 21, 2016, 7:53 PM Tanya Bragin notifications@github.com wrote:

@nik9000 https://github.com/nik9000 That works! So is it paramount that
a well-defined return value is provided for every execution path?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#9171 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AANLonbLflUFEVIFbjCT7t6_EEIEv0cfks5rAj0igaJpZM4K40-z
.

@tbragin
Copy link
Contributor

tbragin commented Nov 22, 2016

So modifying the substring script to be what @nik9000 recommended, namely to ensure the substrings script always returned something, I was able to run all the script examples in the painless blog and filter by them with no problems using this PR on top of Kibana master against latest ES master:
screen shot 2016-11-21 at 5 02 22 pm
screen shot 2016-11-21 at 5 11 36 pm
screen shot 2016-11-21 at 5 11 06 pm

@jdconrad
Copy link

As to the functions -- there isn't necessarily an obvious default return value for functions, unfortunately, as they can be void and return nothing or return a primitive type and maybe a default of 0 makes sense? But maybe that breaks some things. I'm not actually 100% sure as to the behavior of lambdas since Robert Muir did that work, but I would guess it's similar for them. They use something called LambdaMetaFactory (a Java class) that has an insane rule set that I can take a look at tomorrow.

Copy link
Contributor

@stacey-gammon stacey-gammon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactor suggestion, but otherwise, lgtm

if (field.lang === 'painless') {
script = `boolean compare(Supplier s, def v) {return s.get() == v;}
compare(() -> { ${field.script} }, params.value);`;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this could be refactored? getInlineScriptForPhraseFilter, or similar helper function on the field object, perhaps? Then it won't have to be written out three times. I was toying with the idea when I first wrote this fix, but it was going in right before the release so I opted for minimal changes, but now there's a bit more content to be refactored so might be worth it.

@Bargs
Copy link
Contributor Author

Bargs commented Nov 22, 2016

@stacey-gammon Since this logic is highly specific to the phrase filter I was worried about spreading it to the field class, so I exported it as a separate function in the phrase module which can be reused in all three places. A nice side effect is that the test is no longer whitespace dependent, which I didn't like.

I also added some additional tests and included Nik's suggestion. Please take another look and let me know what you think.

Copy link
Contributor

@stacey-gammon stacey-gammon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@Bargs Bargs assigned lukasolson and unassigned stacey-gammon Nov 22, 2016
@epixa epixa merged commit 10eb827 into elastic:master Nov 29, 2016
elastic-jasper added a commit that referenced this pull request Nov 29, 2016
Backports PR #9171

**Commit 1:**
Fix filters for complex painless scripted fields

Painless scripted fields that consisted of more than a single expression
would break when the user attempted to filter on them in Discover or
Visualize because of the naive way we were building them. We now wrap
the user's script in a lambda so that it can be as complex at they need
it to be. The only special exception is that the user cannot define
named functions since those cannot go inside a Painless lambda.

Fixes #9024
Related elastic/elasticsearch#21635

* Original sha: b2a86bb
* Authored by Matthew Bargar <mbargar@gmail.com> on 2016-11-21T23:18:20Z

**Commit 2:**
DRY it up

* Original sha: 927de50
* Authored by Matthew Bargar <mbargar@gmail.com> on 2016-11-22T16:21:21Z

**Commit 3:**
Phrase tests

* Original sha: 79e69bd
* Authored by Matthew Bargar <mbargar@gmail.com> on 2016-11-22T16:48:12Z

**Commit 4:**
Only include necessary comparators and add tests

* Original sha: 5b9137b
* Authored by Matthew Bargar <mbargar@gmail.com> on 2016-11-22T17:38:59Z
elastic-jasper added a commit that referenced this pull request Nov 29, 2016
Backports PR #9171

**Commit 1:**
Fix filters for complex painless scripted fields

Painless scripted fields that consisted of more than a single expression
would break when the user attempted to filter on them in Discover or
Visualize because of the naive way we were building them. We now wrap
the user's script in a lambda so that it can be as complex at they need
it to be. The only special exception is that the user cannot define
named functions since those cannot go inside a Painless lambda.

Fixes #9024
Related elastic/elasticsearch#21635

* Original sha: b2a86bb
* Authored by Matthew Bargar <mbargar@gmail.com> on 2016-11-21T23:18:20Z

**Commit 2:**
DRY it up

* Original sha: 927de50
* Authored by Matthew Bargar <mbargar@gmail.com> on 2016-11-22T16:21:21Z

**Commit 3:**
Phrase tests

* Original sha: 79e69bd
* Authored by Matthew Bargar <mbargar@gmail.com> on 2016-11-22T16:48:12Z

**Commit 4:**
Only include necessary comparators and add tests

* Original sha: 5b9137b
* Authored by Matthew Bargar <mbargar@gmail.com> on 2016-11-22T17:38:59Z
epixa pushed a commit that referenced this pull request Nov 29, 2016
Backports PR #9171

**Commit 1:**
Fix filters for complex painless scripted fields

Painless scripted fields that consisted of more than a single expression
would break when the user attempted to filter on them in Discover or
Visualize because of the naive way we were building them. We now wrap
the user's script in a lambda so that it can be as complex at they need
it to be. The only special exception is that the user cannot define
named functions since those cannot go inside a Painless lambda.

Fixes #9024
Related elastic/elasticsearch#21635

* Original sha: b2a86bb
* Authored by Matthew Bargar <mbargar@gmail.com> on 2016-11-21T23:18:20Z

**Commit 2:**
DRY it up

* Original sha: 927de50
* Authored by Matthew Bargar <mbargar@gmail.com> on 2016-11-22T16:21:21Z

**Commit 3:**
Phrase tests

* Original sha: 79e69bd
* Authored by Matthew Bargar <mbargar@gmail.com> on 2016-11-22T16:48:12Z

**Commit 4:**
Only include necessary comparators and add tests

* Original sha: 5b9137b
* Authored by Matthew Bargar <mbargar@gmail.com> on 2016-11-22T17:38:59Z
epixa pushed a commit that referenced this pull request Nov 29, 2016
Backports PR #9171

**Commit 1:**
Fix filters for complex painless scripted fields

Painless scripted fields that consisted of more than a single expression
would break when the user attempted to filter on them in Discover or
Visualize because of the naive way we were building them. We now wrap
the user's script in a lambda so that it can be as complex at they need
it to be. The only special exception is that the user cannot define
named functions since those cannot go inside a Painless lambda.

Fixes #9024
Related elastic/elasticsearch#21635

* Original sha: b2a86bb
* Authored by Matthew Bargar <mbargar@gmail.com> on 2016-11-21T23:18:20Z

**Commit 2:**
DRY it up

* Original sha: 927de50
* Authored by Matthew Bargar <mbargar@gmail.com> on 2016-11-22T16:21:21Z

**Commit 3:**
Phrase tests

* Original sha: 79e69bd
* Authored by Matthew Bargar <mbargar@gmail.com> on 2016-11-22T16:48:12Z

**Commit 4:**
Only include necessary comparators and add tests

* Original sha: 5b9137b
* Authored by Matthew Bargar <mbargar@gmail.com> on 2016-11-22T17:38:59Z
@epixa epixa added the v5.2.0 label Nov 29, 2016
Bargs added a commit to Bargs/kibana that referenced this pull request Nov 29, 2016
We made a mistake in opening up Kibana scripted fields to any and all
langs enabled in Elasticsearch. Kibana needs to do some magic to get
certain scripted field features to work
(elastic#9171) and we can't commit to
supporting anything beyond expression and painless scripts. On top of
that, the other languages are being removed in ES 6.0 anyway. This commit
makes that stance explicit by disallowing anything other than those two
choices.
Bargs added a commit to Bargs/kibana that referenced this pull request Dec 7, 2016
We made a mistake in opening up Kibana scripted fields to any and all
langs enabled in Elasticsearch. Kibana needs to do some magic to get
certain scripted field features to work
(elastic#9171) and we can't commit to
supporting anything beyond expression and painless scripts. On top of
that, the other languages are being removed in ES 6.0 anyway. This commit
makes that stance explicit by disallowing anything other than those two
choices.
Bargs pushed a commit that referenced this pull request Dec 12, 2016
We made a mistake in opening up Kibana scripted fields to any and all
langs enabled in Elasticsearch. Kibana needs to do some magic to get
certain scripted field features to work
(#9171) and we can't commit to
supporting anything beyond expression and painless scripts. On top of
that, the other languages are being removed in ES 6.0 anyway. This commit
makes that stance explicit by disallowing anything other than those two
choices.
airow pushed a commit to airow/kibana that referenced this pull request Feb 16, 2017
Backports PR elastic#9171

**Commit 1:**
Fix filters for complex painless scripted fields

Painless scripted fields that consisted of more than a single expression
would break when the user attempted to filter on them in Discover or
Visualize because of the naive way we were building them. We now wrap
the user's script in a lambda so that it can be as complex at they need
it to be. The only special exception is that the user cannot define
named functions since those cannot go inside a Painless lambda.

Fixes elastic#9024
Related elastic/elasticsearch#21635

* Original sha: b2a86bb
* Authored by Matthew Bargar <mbargar@gmail.com> on 2016-11-21T23:18:20Z

**Commit 2:**
DRY it up

* Original sha: 927de50
* Authored by Matthew Bargar <mbargar@gmail.com> on 2016-11-22T16:21:21Z

**Commit 3:**
Phrase tests

* Original sha: 79e69bd
* Authored by Matthew Bargar <mbargar@gmail.com> on 2016-11-22T16:48:12Z

**Commit 4:**
Only include necessary comparators and add tests

* Original sha: 5b9137b
* Authored by Matthew Bargar <mbargar@gmail.com> on 2016-11-22T17:38:59Z

Former-commit-id: 313794b
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants