-
Notifications
You must be signed in to change notification settings - Fork 24.9k
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
Make ScriptFieldMapper a parameterized mapper #59391
Make ScriptFieldMapper a parameterized mapper #59391
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, I think we should look into making ScriptService available via the parser context which should clear up the SetOnce nastiness.
...ime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptFieldMapper.java
Outdated
Show resolved
Hide resolved
} | ||
} | ||
|
||
public static class TypeParser implements Mapper.TypeParser { | ||
|
||
private final SetOnce<ScriptService> scriptService = new SetOnce<>(); | ||
// TODO this is quite ugly and it's static which makes it even worse | ||
private static final SetOnce<ScriptService> SCRIPT_SERVICE = new SetOnce<>(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there no way of getting it via the ParserContext
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks as though we'd have to wire ScriptService
into MapperService
, but I think that's a reasonable thing to do
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will look into it, thanks for the suggestion.
...ime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptFieldMapper.java
Outdated
Show resolved
Hide resolved
) { | ||
super(simpleName, mappedFieldType, multiFields, copyTo); | ||
// TODO is it ok that the object being built needs to read from the object that is building it? Shouldn't Builder#build return | ||
// a complete object? Maybe all the parameters need to be passed through instead of the whole builder? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@romseygeek this is for you, does it make sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that the mapper constructor is protected here, I think it's OK? You can pull out individual parameters if you think it's clearer, I used this pattern on other mappers simply because otherwise you end up with 14 constructor parameters most of which are just boilerplate.
null | ||
); | ||
// TODO script and runtime_type can be updated: what happens to the currently running queries when they get updated? | ||
// do all the shards get a consistent view? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@romseygeek do you have thoughts on this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So currently QueryShardContext#fieldMapper()
delegates field lookups back to the MapperService, which gets updated in-place, so if there's an update while a query is running then the script will get changed out and there may well be inconsistencies between phases, as well as between shards. We could make QueryShardContext take a FieldTypeLookup as a parameter which would at least remove the possibility of an update between phases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have this sort of problem now with any thing that can change. I guess scripts make this worse because they are "more mutable" than other stuff.
} else { | ||
throw new IllegalArgumentException("runtime_type [" + runtimeType + "] not supported"); | ||
} | ||
// TODO copy to and multi_fields... not sure what needs to be done. | ||
return new ScriptFieldMapper(name, mappedFieldType, multiFieldsBuilder.build(this, context), copyTo); | ||
// TODO copy to and multi_fields should not be supported, parametrized field mapper needs to be adapted |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@romseygeek and this one too. I think I would prefer making the changes upstream instead of adapting parameterized field mapper in the feature branch. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
++, I can work on this one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks that would be great!
Pinging @elastic/es-search (:Search/Search) |
This is now ready. There are two TODOs left to address which can be addressed later:
|
assertEquals("Failed to parse mapping: script must be specified for script field [my_field]", exception.getMessage()); | ||
} | ||
|
||
@AwaitsFix(bugUrl = "Nik: help! :)") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nik9000 help!
null | ||
); | ||
// TODO script and runtime_type can be updated: what happens to the currently running queries when they get updated? | ||
// do all the shards get a consistent view? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have this sort of problem now with any thing that can change. I guess scripts make this worse because they are "more mutable" than other stuff.
|
||
private final SetOnce<ScriptService> scriptService = new SetOnce<>(); | ||
@SuppressWarnings("unchecked") | ||
static Script parseScript(String name, Mapper.TypeParser.ParserContext parserContext, Object scriptObject) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I swear I've seen this before somewhere else...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you may have, but we only accept painless and we don't parse stored scripts. I will look though, I assumed that we never parse from a map but watcher may do that actually.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found it, it was in update by query, I opened #59507 so that we can test and reuse that existing code
// TODO these get passed in sometimes and we don't need them | ||
node.remove("doc_values"); | ||
node.remove("index"); | ||
ScriptFieldMapper.Builder builder = new ScriptFieldMapper.Builder(name, parserContext.queryShardContextSupplier()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think queryShardContextSupplier
exists for the percolator and it is a bit sneaky. It'll do but I'd feel more comfortable if we had the ScriptService
directly.
super(simpleName, mappedFieldType, multiFields, copyTo); | ||
this.runtimeType = runtimeType; | ||
this.script = script; | ||
this.queryShardContextSupplier = queryShardContextSupplier; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I worry about keeping the queryShardContextSupplier
around because it is sneaky. Could getMergeBuilder
get the parse context or something like that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. I personally prefer the hack that we had before (SetOnce in the type parser, set from the plugin class). Otherwise I can get the query shard context from the parser context and pass in only the script service, hopefully it is available.
...ime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/mapper/ScriptFieldMapper.java
Outdated
Show resolved
Hide resolved
} | ||
|
||
@AwaitsFix(bugUrl = "Nik: help! :)") | ||
public void testDefaultMapping() throws Exception { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the idea to test that we can properly parse a simple version of the mapper? I don't really get the name of the method. I will try and hack on it locally and let you know what I find.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the name is from a copy/paste. I wanted to test that the mapper works indeed.
The update by query action parses a script from an object (map or string). We will need to do the same for runtime fields as they are parsed as part of mappings (elastic#59391). This commit moves the existing parsing of a script from an object from RestUpdateByQueryAction to the Script class. It also adds tests and adjusts some error messages that are incorrect. Also, options were not parsed before and they are now. And unsupported fields are no longer silently ignored.
The update by query action parses a script from an object (map or string). We will need to do the same for runtime fields as they are parsed as part of mappings (elastic#59391). This commit moves the existing parsing of a script from an object from RestUpdateByQueryAction to the Script class. It also adds tests and adjusts some error messages that are incorrect. Also, options were not parsed before and they are now. And unsupported fields are no longer silently ignored.
The update by query action parses a script from an object (map or string). We will need to do the same for runtime fields as they are parsed as part of mappings (#59391). This commit moves the existing parsing of a script from an object from RestUpdateByQueryAction to the Script class. It also adds tests and adjusts some error messages that are incorrect. Also, options were not parsed before and they are now. And unsupported fields are no longer silently ignored.
I addressed another TODO around the type to be returned and a couple of issues around field caps, as well as added a test for field_caps. This should be ready. I'd like to discuss separately what we should do to clean up how get the reference to ScriptService. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
The update by query action parses a script from an object (map or string). We will need to do the same for runtime fields as they are parsed as part of mappings (#59391). This commit moves the existing parsing of a script from an object from RestUpdateByQueryAction to the Script class. It also adds tests and adjusts some error messages that are incorrect. Also, options were not parsed before and they are now. And unsupported fields trigger now a deprecation warning.
This PR is opened against the runtime fields feature branch.
Relates to #59332