-
Notifications
You must be signed in to change notification settings - Fork 25.2k
Painless as a JSON-friendly templating language #24529
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
Comments
CC @jdconrad, @nik9000, @s1monw, @spinscale, @colings86, @talevy |
I haven't thought through the syntax all the way (although |
when playing around with a new templating language, we started using
why does it need a different grammar? users already use painless, why do they need to learn a new language for the templating? remember that 90% of use cases will be simple value substitution |
+1, this is something I have in mind since Painless went out and I think @jdconrad thought about it too (it reminds me the JSP with We added some functions to Mustache like |
My concern with the proposal as it stands, is that it's a bit "magical" when it comes to dealing with a template-expression inside of quotes.
The spec would be something like:
(*) Or should be that be the Stringification of its JSON representation? It's user friendly 99% of the time, but it feels like a little bit too much magic to describe and explain well. That said, I don't have an alternative that I like.
|
I thought this could be a solution that would force the user to do something like this instead:
But that makes it harder to write things like:
|
@rjernst I think what @clintongormley is saying is that we would simply parse JSON and if we see a string sequence |
I realized that much later after my initial comment. But I agree with @tvernum's sentiment that this magic value handling will be error prone. I think instead we should do 2 things:
So, with my proposal, the example between @clintongormley and @tvernum above could be done a few ways:
Alternatively, if we don't want to add variable substitution in painless strings, we could just use two different characters to mean "replace the node" vs "replace the contents of the string". But for both, I would just use a single character at the beginning of the string (and in both cases, the rest of the string is all painless code).
I think we can make this work, by painless knowing handling the entire template. @jdconrad and I thought through this when working on scripting contexts, and I think this can still be achieved by painless taking in the entire json object, and compiling that into a script which makes statements for each substituted element, and then joins them together into a serialized json string at the end. |
But it is a common character in strings, eg ref numbers. Btw, I'm not tied to
I think this makes the simple case really ugly, eg compare:
with
|
No matter which character(s) is/are used, they are possible in strings, and so escaping will be necessary to use it at the beginning of a string.
Ugly is better than trappy. But I think if we have string substitution, we don't need to use the node replacement character at the beginning:
|
++ I ran into exactly this surrounding-quote-when-rendering-lists problem when testing x-pack security role template queries. The resulting stringified JSON query was ugly and hard to maintain. |
Pinging @elastic/es-core-infra (:Core/Infra/Scripting) |
Since this is part of the indices api project, I'd like to discuss in a broader group to see if this is still useful. |
I have found this issue via #50923 and I really hope to see search templating improved in the future. Just to make sure the following use case will be covered as well, since this is a widely known mustache problem of current implementation, what I was trying to build is someting like this.
The problem is that this will not work since the entries are not comma separated and if y comma is inserted in the template then it is added to the last entry as well. The only solution was to turn stats-fields in a list of maps and use a has-next key to add the comma conditionally, inspired by this. This works for the moment but is IMHO more a workaround than a solution. |
As a side note, one of my approaches to solve the problem was to change the content/type and build the whole template in yaml, since yaml does not need comma separation. This approach was not working either. Mustache was partially working by creating escaped output strings instead of hash object and I finally gave up on it. But again, please consider proper yaml support as well, since yaml is much easier to work with than json, ist human friendlier and supports comments. |
This issue has sat open for many years, and while there are several good ideas in it, there are two main problems with moving forward. The first is that this issue is loosely designed to work with Painless, but in reality it lacks semantic integration with Painless. A performant implementation of this would need to collapse many disparate Painless snippets into a runtime that fills in the holes in the template. Additionally, this would need to join these snippets together after running them, and then adhere to the template script context. And finally, the script context itself really needs to change. Right now it is a String to String method, but to be efficient we really want to have the json parsed (partially?), and passed in. There is quite a bit of technical scoping that would still need to happen here, so it is a very high hanging fruit. The second reason is a direct result of the above: the benefit of this work compared to the cost is low. While Mustache has its deficiencies, it has worked well enough to get by for many years. This issue would bring improvements, but Mustache would also likely need to change to conform to the template script context changes, thereby further increasing the cost. Ultimately, this issue has sat relatively untouched for almost 4 years. After discussing recently among the scripting folks, we agreed this is not worth keeping open, since any change in priorities to work on it would likely want to start fresh, and the scope is such that the |
The problem
Today our only choice for a templating language is Mustache which, while fine for very simple templates, does not work well in the JSON context where we mostly use it (eg search templates, watches etc).
For instance, if you want to return an array of terms in a query, you can't do:
because that would render as:
Instead, the whole template has to be passed as one big string in order to remove the double quotes:
Dealing with big queries as a string instead of as a JSON structure is complicated, finicky, and error prone.
On top of that, Mustache's limited support for defaults, conditionals, etc make anything but variable substitution difficult and hacky. Just see https://www.elastic.co/guide/en/elasticsearch/reference/5.4/search-template.html#_conditional_clauses as an example of how ugly it can get.
Making it JSON friendly
Instead, we need a templating solution where JSON is parsed as JSON, and any string element is treated as a potential template, the result of which can be any JSON-compatible data structure.
For instance:
Additionally, templates can be embedded in strings in combination with non-templated strings:
Any JSON-compatible data structure could be stringified to its JSON equivalent when used as an embedded template, eg:
Templates in JSON keys would always be stringified.
Using Painless
Painless is a fast, safe, and powerful scripting language with strong typing; in other words, parameters retain their types instead of just being considered as strings, in the way Mustache does.
Painless can be used as is with a wrapper implementing the stringification mentioned above. By far the majority of templates use simple value substitution:
Default values:
Conditionals:
String manipulation:
It could also be extended to make common templating use cases more succinct, eg
params.num || 10
map
andfilter
functions for list manipulationOf course, these additions would be backwards compatible, so old templates will keep working while new templates can take advantage of any new syntax.
The text was updated successfully, but these errors were encountered: