Formal spec for Query DSL

Hiya

I'm trying to formalise the spec for the Query DSL used by
ElasticSearch, both for my own understanding, and for making the Perl
API more aware. The current docs assume a working knowledge of
Lucene, which I don't have, so I'm writing this email to have my
assumptions checked.

Below I've broken down all possible values that a query can have.
Please could you check through it and make sure I'm not missing
anything.

Notes:

  1. I've assumed that the various Filters are essentially the same as
    the related Query, but without a "boost", and, where appropriate,
    accepting other FILTER_CLAUSEs instead of other QUERY_CLAUSEs
  2. I think that filteredQuery.filter should accept an array of filters
    as well (as bool.must does)
  3. Am I right in saying that /_count and delete_by_query accept a
    QUERY_CLAUSE?
  4. This correct: "term"s are for pre-tokenised values, while
    "queryString" is for text/phrases that need to be parsed?
  5. In queryString, what do "prefix field", "enablePositionIncrements"
    and "fuzzyPrefixLength" mean?

thanks

Clint

QUERY DSL SPEC: (better read in fixed-width font)

curl -XGET 'http://$server/_all/_search -d '{ TOPLEVEL }'
curl -XGET 'http://$server/_all/$types/_search -d '{ TOPLEVEL }'
curl -XGET 'http://$server/$indices/_search -d '{ TOPLEVEL }'
curl -XGET 'http://$server/$indices/$types/_search -d '{ TOPLEVEL }'

TOPLEVEL:

{
explain: BOOL,
from: INT,
size: INT,
fields: ["field_1", "field_n"],
query: { QUERY_CLAUSE },
facets: { FACETS_CLAUSE },
sort: { SORT_CLAUSE }
}

QUERY_CLAUSE:

{
term: { TERM_QUERY }
| range: { RANGE_QUERY }
| prefix: { PREFIX_QUERY }
| wildcard: { WILDCARD_QUERY }
| matchAll: { MATCH_ALL_QUERY }
| queryString: { QUERY_STRING_QUERY }
| bool: { BOOLEAN_QUERY }
| disMax: { DISMAX_QUERY }
| constantScore: { CONSTANT_SCORE_QUERY }
| filteredQuery: { FILTERED_QUERY },
}

FILTER_CLAUSE:

{
query: { QUERY_CLAUSE },
| term: { TERM_FILTER },
| range: { RANGE_FILTER },
| prefix: { PREFIX_FILTER },
| wildcard: { WILDCARD_FILTER },
| bool: { BOOLEAN_FILTER },
| constantScore: { CONSTANT_SCORE_QUERY }
}

FACETS_CLAUSE:

{
$facet_name_1: { FILTER_CLAUSE },
$facet_name_n: ...
}

SORT_CLAUSE:

{
$fieldname_1 | "score" : {} | { reverse: BOOL },
$fieldname_n | "score" : ...
}

TERM_FILTER:

{ $fieldname_1: VALUE_1, $fieldname_n: VALUE_n }

TERM_QUERY:

TERM_FILTER
| {
$fieldname_1: { value: VALUE_1, boost: FLOAT_1 },
$fieldname_n: ...
}

PREFIX_FILTER:

{ $fieldname_1: STRING_1, $fieldname_n: STRING_n }

PREFIX_QUERY:

PREFIX_FILTER
| {
$fieldname_1: { prefix: STRING_1, boost: FLOAT_1 },
$fieldname_n: ...
}

WILDCARD_FILTER:

{ $fieldname_1: STRING_1, $fieldname_n: STRING_n }

WILDCARD_QUERY:

WILDCARD_FILTER
| {
$fieldname_1: { wildcard: STRING_1, boost: FLOAT_1 },
$fieldname_n: ...
}

MATCH_ALL_QUERY:

{}
| { boost: FLOAT }

RANGE_FILTER:

{   $fieldname:  {
        from:           INT | FLOAT | STRING,
        to:             INT | FLOAT | STRING,
        includeLower:   BOOL,
        includeUpper:   BOOL,
}}

RANGE_QUERY:

{   $fieldname:  {
        from:           INT | FLOAT | STRING,
        to:             INT | FLOAT | STRING,
        includeLower:   BOOL
        includeUpper:   BOOL
        boost:          FLOAT
}}

BOOLEAN_FILTER:

{
    must:     { FILTER_CLAUSE } | [ { FILTER_CLAUSE }, ... ],
    should:   { FILTER_CLAUSE } | [ { FILTER_CLAUSE }, ... ],
    mustNot:  { FILTER_CLAUSE } | [ { FILTER_CLAUSE }, ... ],

    minimumNumberShouldMatch:   INT
}

BOOLEAN_QUERY:

{
    must:     { QUERY_CLAUSE} | [ { QUERY_CLAUSE }, ... ],
    should:   { QUERY_CLAUSE} | [ { QUERY_CLAUSE }, ... ],
    mustNot:  { QUERY_CLAUSE} | [ { QUERY_CLAUSE }, ... ],

    boost:    FLOAT,
    minimumNumberShouldMatch:   INT
}

DISMAX_QUERY:

{
    queries:                [ { QUERY_CLAUSE }, ... ],
    tieBreakerMultiplier:   FLOAT,
    boost:                  FLOAT
}

CONSTANT_SCORE_QUERY:

{
    filter: { FILTER_CLAUSE }
    boost:  FLOAT
}

FILTERED_QUERY:

{
    query:  { QUERY_CLAUSE       },
    filter: { FILTER_CLAUSE, ... }
}

QUERY_STRING_QUERY:

{
query: STRING,
defaultField: $fieldname,
defaultOperator: "AND" | "OR",
analyzer: STRING,
allowLeadingWildcard: BOOL,
lowercaseExpandedTerms: BOOL,
enablePositionIncrements: BOOL,
fuzzyPrefixLength: BOOL,
fuzzyMinSim: FLOAT,
phraseSlop: INT,
boost: FLOAT
}

ARGUMENT TYPES:

  • BOOL: true | false
  • INT: integer eg 5
  • FLOAT: float eg 1.2
  • STRING: text eg "foo"
  • VALUE: BOOL | INT | FLOAT | STRING

Hi,

Answers below:

On Fri, Feb 19, 2010 at 5:48 PM, Clinton clinton@iannounce.co.uk wrote:

Hiya

I'm trying to formalise the spec for the Query DSL used by
Elasticsearch, both for my own understanding, and for making the Perl
API more aware. The current docs assume a working knowledge of
Lucene, which I don't have, so I'm writing this email to have my
assumptions checked.

Below I've broken down all possible values that a query can have.
Please could you check through it and make sure I'm not missing
anything.

Notes:

  1. I've assumed that the various Filters are essentially the same as
    the related Query, but without a "boost", and, where appropriate,
    accepting other FILTER_CLAUSEs instead of other QUERY_CLAUSEs

Yes, they are very similar.

  1. I think that filteredQuery.filter should accept an array of filters
    as well (as bool.must does)

But then how should the relationship between filters be treated? The idea is
that if you want more than one filter, simply create a bool filter and add
filters to it.

  1. Am I right in saying that /_count and delete_by_query accept a
    QUERY_CLAUSE?

Yes.

  1. This correct: "term"s are for pre-tokenised values, while
    "queryString" is for text/phrases that need to be parsed?

Term query will match on the tokens that have been produced by the tokenizer
and indexed. A query string tokenizes the query string and creates token
queries (among others) from it.

  1. In queryString, what do "prefix field", "enablePositionIncrements"
    and "fuzzyPrefixLength" mean?

Where did you see "prefix field"? "enablePositionIncrements" (or positions
in general) relate to the position of the tokens. Its important because some
analyzers / tokenizers can, for example, remove tokens (like the stop
filter), and in such cases, maintaining positions is important for things
that relate to them (like phrase query, ".... ... ").

thanks

Clint

QUERY DSL SPEC: (better read in fixed-width font)

Also (which is like _all), thats in master:
curl -XGET 'http://$server/_search -d '{ TOPLEVEL }'

curl -XGET 'http://$server/_all/_search -d '{ TOPLEVEL }'

curl -XGET 'http://$server/_all/$types/_search -d '{ TOPLEVEL }'
curl -XGET 'http://$server/$indices/_search -d '{ TOPLEVEL }'
curl -XGET 'http://$server/$indices/$types/_search -d '{ TOPLEVEL }'

TOPLEVEL:

{
explain: BOOL,
from: INT,
size: INT,
fields: ["field_1", "field_n"],
query: { QUERY_CLAUSE },
facets: { FACETS_CLAUSE },
sort: { SORT_CLAUSE }
}

QUERY_CLAUSE:

{
term: { TERM_QUERY }
| range: { RANGE_QUERY }
| prefix: { PREFIX_QUERY }
| wildcard: { WILDCARD_QUERY }
| matchAll: { MATCH_ALL_QUERY }
| queryString: { QUERY_STRING_QUERY }
| bool: { BOOLEAN_QUERY }
| disMax: { DISMAX_QUERY }
| constantScore: { CONSTANT_SCORE_QUERY }
| filteredQuery: { FILTERED_QUERY },
}

FILTER_CLAUSE:

{
query: { QUERY_CLAUSE },
| term: { TERM_FILTER },
| range: { RANGE_FILTER },
| prefix: { PREFIX_FILTER },
| wildcard: { WILDCARD_FILTER },
| bool: { BOOLEAN_FILTER },
| constantScore: { CONSTANT_SCORE_QUERY }
}

FACETS_CLAUSE:

{
$facet_name_1: { FILTER_CLAUSE },
$facet_name_n: ...
}

Facets accept a QUERY_CLAUSE not a FILTER_CLAUSE.

SORT_CLAUSE:

{
$fieldname_1 | "score" : {} | { reverse: BOOL },
$fieldname_n | "score" : ...
}

TERM_FILTER:

{ $fieldname_1: VALUE_1, $fieldname_n: VALUE_n }

Term filter only accept one field and value. If you want to filter on
several terms, use a bool filter to wrap several term filters.

TERM_QUERY:

TERM_FILTER
| {
$fieldname_1: { value: VALUE_1, boost: FLOAT_1 },
$fieldname_n: ...
}

Same as Term filter, only one field and value. Why do you have term filter
there?

PREFIX_FILTER:

{ $fieldname_1: STRING_1, $fieldname_n: STRING_n }

Just one field and value allowed.

PREFIX_QUERY:

PREFIX_FILTER
| {
$fieldname_1: { prefix: STRING_1, boost: FLOAT_1 },
$fieldname_n: ...
}

Same as prefix filter, just one field and value allowed. Why do you have
prefix filter there?

WILDCARD_FILTER:

{ $fieldname_1: STRING_1, $fieldname_n: STRING_n }

Just one field name and value allowed.

WILDCARD_QUERY:

WILDCARD_FILTER
| {
$fieldname_1: { wildcard: STRING_1, boost: FLOAT_1 },
$fieldname_n: ...
}

Just one field name and value allowed.

MATCH_ALL_QUERY:

{}
| { boost: FLOAT }

RANGE_FILTER:

{ $fieldname: {
from: INT | FLOAT | STRING,
to: INT | FLOAT | STRING,
includeLower: BOOL,
includeUpper: BOOL,
}}

RANGE_QUERY:

{ $fieldname: {
from: INT | FLOAT | STRING,
to: INT | FLOAT | STRING,
includeLower: BOOL
includeUpper: BOOL
boost: FLOAT
}}

BOOLEAN_FILTER:

{
must: { FILTER_CLAUSE } | [ { FILTER_CLAUSE }, ... ],
should: { FILTER_CLAUSE } | [ { FILTER_CLAUSE }, ... ],
mustNot: { FILTER_CLAUSE } | [ { FILTER_CLAUSE }, ... ],

   minimumNumberShouldMatch:   INT

}

BOOLEAN_QUERY:

{
must: { QUERY_CLAUSE} | [ { QUERY_CLAUSE }, ... ],
should: { QUERY_CLAUSE} | [ { QUERY_CLAUSE }, ... ],
mustNot: { QUERY_CLAUSE} | [ { QUERY_CLAUSE }, ... ],

   boost:    FLOAT,
   minimumNumberShouldMatch:   INT

}

DISMAX_QUERY:

{
queries: [ { QUERY_CLAUSE }, ... ],
tieBreakerMultiplier: FLOAT,
boost: FLOAT
}

CONSTANT_SCORE_QUERY:

{
filter: { FILTER_CLAUSE }
boost: FLOAT
}

FILTERED_QUERY:

{
query: { QUERY_CLAUSE },
filter: { FILTER_CLAUSE, ... }
}

QUERY_STRING_QUERY:

{
query: STRING,
defaultField: $fieldname,
defaultOperator: "AND" | "OR",
analyzer: STRING,
allowLeadingWildcard: BOOL,
lowercaseExpandedTerms: BOOL,
enablePositionIncrements: BOOL,
fuzzyPrefixLength: BOOL,
fuzzyMinSim: FLOAT,
phraseSlop: INT,
boost: FLOAT
}

ARGUMENT TYPES:

  • BOOL: true | false
  • INT: integer eg 5
  • FLOAT: float eg 1.2
  • STRING: text eg "foo"
  • VALUE: BOOL | INT | FLOAT | STRING

Hiya

    2) I think that filteredQuery.filter should accept an array of
    filters
    as well (as bool.must does)

But then how should the relationship between filters be treated? The
idea is that if you want more than one filter, simply create a bool
filter and add filters to it.

Ah ok - gotcha

    5) In queryString, what do "prefix field",
    "enablePositionIncrements"
    and "fuzzyPrefixLength" mean?

Where did you see "prefix field"?

In the docs on
http://www.elasticsearch.com/docs/elasticsearch/rest_api/query_dsl/

you have:

defaultField:  The default field for query terms if no prefix field
               is specified. 

Based on your comments, I've update my DSL spec. Would it be worth
putting this on the website?

QUERY DSL SPEC: (better read in fixed-width font)

curl -XGET 'http://$server/_search -d '{ TOPLEVEL }'
curl -XGET 'http://$server/_all/_search -d '{ TOPLEVEL }'
curl -XGET 'http://$server/_all/$types/_search -d '{ TOPLEVEL }'
curl -XGET 'http://$server/$indices/_search -d '{ TOPLEVEL }'
curl -XGET 'http://$server/$indices/$types/_search -d '{ TOPLEVEL }'

TOPLEVEL:

{
explain: BOOL,
from: INT,
size: INT,
fields: ["field_1", "field_n"],
query: { QUERY_CLAUSE },
facets: { FACETS_CLAUSE },
sort: { SORT_CLAUSE }
}

QUERY_CLAUSE:

{
term: { TERM_QUERY }
| range: { RANGE_QUERY }
| prefix: { PREFIX_QUERY }
| wildcard: { WILDCARD_QUERY }
| matchAll: { MATCH_ALL_QUERY }
| queryString: { QUERY_STRING_QUERY }
| bool: { BOOLEAN_QUERY }
| disMax: { DISMAX_QUERY }
| constantScore: { CONSTANT_SCORE_QUERY }
| filteredQuery: { FILTERED_QUERY },
}

FILTER_CLAUSE:

{
query: { QUERY_CLAUSE },
| term: { TERM_FILTER },
| range: { RANGE_FILTER },
| prefix: { PREFIX_FILTER },
| wildcard: { WILDCARD_FILTER },
| bool: { BOOLEAN_FILTER },
| constantScore: { CONSTANT_SCORE_QUERY }
}

FACETS_CLAUSE:

{
$facet_name_1: { QUERY_CLAUSE },
$facet_name_n: ...
}

SORT_CLAUSE:

[
$fieldname_1 | "score
| { $fieldname_1 : { reverse: BOOL }},
...
]

TERM_FILTER:

{ $fieldname: VALUE_1 }

TERM_QUERY:

{ $fieldname: VALUE_1 }
| { $fieldname: { value: VALUE, boost: FLOAT } }

PREFIX_FILTER:

{ $fieldname: STRING}

PREFIX_QUERY:

{ $fieldname: STRING}
| { $fieldname: { prefix: STRING_1, boost: FLOAT } }

WILDCARD_FILTER:

{ $fieldname: STRING }

WILDCARD_QUERY:

{ $fieldname: STRING }
| { $fieldname: { wildcard: STRING, boost: FLOAT } }

MATCH_ALL_QUERY:

{}
| { boost: FLOAT }

RANGE_FILTER:

{   $fieldname:  {
        from:           INT | FLOAT | STRING | DATETIME,
        to:             INT | FLOAT | STRING | DATETIME,
        includeLower:   BOOL,
        includeUpper:   BOOL,
}}

RANGE_QUERY:

{   $fieldname:  {
        from:           INT | FLOAT | STRING | DATETIME,
        to:             INT | FLOAT | STRING | DATETIME,
        includeLower:   BOOL
        includeUpper:   BOOL
        boost:          FLOAT        
}}

BOOLEAN_FILTER:

{
    must:     { FILTER_CLAUSE } | [ { FILTER_CLAUSE }, ... ],
    should:   { FILTER_CLAUSE } | [ { FILTER_CLAUSE }, ... ],
    mustNot:  { FILTER_CLAUSE } | [ { FILTER_CLAUSE }, ... ],
    
    minimumNumberShouldMatch:   INT
}

BOOLEAN_QUERY:

{
    must:     { QUERY_CLAUSE} | [ { QUERY_CLAUSE }, ... ],
    should:   { QUERY_CLAUSE} | [ { QUERY_CLAUSE }, ... ],
    mustNot:  { QUERY_CLAUSE} | [ { QUERY_CLAUSE }, ... ],
    
    boost:    FLOAT,
    minimumNumberShouldMatch:   INT
}

DISMAX_QUERY:

{
    queries:                [ { QUERY_CLAUSE }, ... ],
    tieBreakerMultiplier:   FLOAT,
    boost:                  FLOAT
}

CONSTANT_SCORE_QUERY:

{
    filter: { FILTER_CLAUSE }
    boost:  FLOAT
}

FILTERED_QUERY:

{
    query:  { QUERY_CLAUSE       },
    filter: { FILTER_CLAUSE, ... }
}

QUERY_STRING_QUERY:

{
query: STRING,
defaultField: $fieldname,
defaultOperator: "AND" | "OR",
analyzer: STRING,
allowLeadingWildcard: BOOL,
lowercaseExpandedTerms: BOOL,
enablePositionIncrements: BOOL,
fuzzyPrefixLength: BOOL,
fuzzyMinSim: FLOAT,
phraseSlop: INT,
boost: FLOAT
}

ARGUMENT TYPES:

  • BOOL: true | false
  • INT: integer eg 5
  • FLOAT: float eg 1.2
  • STRING: text eg "foo"
  • DATETIME: dates and times
    eg "2010-02-31T13:30:45", "2010-02-31", "13:30:45"
  • VALUE: BOOL | INT | FLOAT | STRING | DATETIME

thanks

clint

--
Web Announcements Limited is a company registered in England and Wales,
with company number 05608868, with registered address at 10 Arvon Road,
London, N5 1PR.

Regarding the field, what I meant by a prefix field is that you can execute
a query string with "fieldA:valueA", in this case, you have a prefix field
for valueA, but, you can also execute a query with just "valueA", in this
case, it will run against the defaultField.

Regarding the spec, can you send it to me as a txt file and I will add it to
the site.

Thanks for the effort!
Shay

On Sat, Feb 20, 2010 at 6:22 PM, Clinton Gormley clinton@iannounce.co.ukwrote:

Hiya

    2) I think that filteredQuery.filter should accept an array of
    filters
    as well (as bool.must does)

But then how should the relationship between filters be treated? The
idea is that if you want more than one filter, simply create a bool
filter and add filters to it.

Ah ok - gotcha

    5) In queryString, what do "prefix field",
    "enablePositionIncrements"
    and "fuzzyPrefixLength" mean?

Where did you see "prefix field"?

In the docs on
http://www.elasticsearch.com/docs/elasticsearch/rest_api/query_dsl/

you have:

defaultField: The default field for query terms if no prefix field
is specified.

Based on your comments, I've update my DSL spec. Would it be worth
putting this on the website?

QUERY DSL SPEC: (better read in fixed-width font)

curl -XGET 'http://$server/_search -d '{ TOPLEVEL }'
curl -XGET 'http://$server/_all/_search -d '{ TOPLEVEL }'
curl -XGET 'http://$server/_all/$types/_search -d '{ TOPLEVEL }'
curl -XGET 'http://$server/$indices/_search -d '{ TOPLEVEL }'
curl -XGET 'http://$server/$indices/$types/_search -d '{ TOPLEVEL }'

TOPLEVEL:

{
explain: BOOL,
from: INT,
size: INT,
fields: ["field_1", "field_n"],
query: { QUERY_CLAUSE },
facets: { FACETS_CLAUSE },
sort: { SORT_CLAUSE }
}

QUERY_CLAUSE:

{
term: { TERM_QUERY }
| range: { RANGE_QUERY }
| prefix: { PREFIX_QUERY }
| wildcard: { WILDCARD_QUERY }
| matchAll: { MATCH_ALL_QUERY }
| queryString: { QUERY_STRING_QUERY }
| bool: { BOOLEAN_QUERY }
| disMax: { DISMAX_QUERY }
| constantScore: { CONSTANT_SCORE_QUERY }
| filteredQuery: { FILTERED_QUERY },
}

FILTER_CLAUSE:

{
query: { QUERY_CLAUSE },
| term: { TERM_FILTER },
| range: { RANGE_FILTER },
| prefix: { PREFIX_FILTER },
| wildcard: { WILDCARD_FILTER },
| bool: { BOOLEAN_FILTER },
| constantScore: { CONSTANT_SCORE_QUERY }
}

FACETS_CLAUSE:

{
$facet_name_1: { QUERY_CLAUSE },
$facet_name_n: ...
}

SORT_CLAUSE:

[
$fieldname_1 | "score
| { $fieldname_1 : { reverse: BOOL }},
...
]

TERM_FILTER:

{ $fieldname: VALUE_1 }

TERM_QUERY:

{ $fieldname: VALUE_1 }
| { $fieldname: { value: VALUE, boost: FLOAT } }

PREFIX_FILTER:

{ $fieldname: STRING}

PREFIX_QUERY:

{ $fieldname: STRING}
| { $fieldname: { prefix: STRING_1, boost: FLOAT } }

WILDCARD_FILTER:

{ $fieldname: STRING }

WILDCARD_QUERY:

{ $fieldname: STRING }
| { $fieldname: { wildcard: STRING, boost: FLOAT } }

MATCH_ALL_QUERY:

{}
| { boost: FLOAT }

RANGE_FILTER:

{ $fieldname: {
from: INT | FLOAT | STRING | DATETIME,
to: INT | FLOAT | STRING | DATETIME,
includeLower: BOOL,
includeUpper: BOOL,
}}

RANGE_QUERY:

{ $fieldname: {
from: INT | FLOAT | STRING | DATETIME,
to: INT | FLOAT | STRING | DATETIME,
includeLower: BOOL
includeUpper: BOOL
boost: FLOAT
}}

BOOLEAN_FILTER:

{
must: { FILTER_CLAUSE } | [ { FILTER_CLAUSE }, ... ],
should: { FILTER_CLAUSE } | [ { FILTER_CLAUSE }, ... ],
mustNot: { FILTER_CLAUSE } | [ { FILTER_CLAUSE }, ... ],

   minimumNumberShouldMatch:   INT

}

BOOLEAN_QUERY:

{
must: { QUERY_CLAUSE} | [ { QUERY_CLAUSE }, ... ],
should: { QUERY_CLAUSE} | [ { QUERY_CLAUSE }, ... ],
mustNot: { QUERY_CLAUSE} | [ { QUERY_CLAUSE }, ... ],

   boost:    FLOAT,
   minimumNumberShouldMatch:   INT

}

DISMAX_QUERY:

{
queries: [ { QUERY_CLAUSE }, ... ],
tieBreakerMultiplier: FLOAT,
boost: FLOAT
}

CONSTANT_SCORE_QUERY:

{
filter: { FILTER_CLAUSE }
boost: FLOAT
}

FILTERED_QUERY:

{
query: { QUERY_CLAUSE },
filter: { FILTER_CLAUSE, ... }
}

QUERY_STRING_QUERY:

{
query: STRING,
defaultField: $fieldname,
defaultOperator: "AND" | "OR",
analyzer: STRING,
allowLeadingWildcard: BOOL,
lowercaseExpandedTerms: BOOL,
enablePositionIncrements: BOOL,
fuzzyPrefixLength: BOOL,
fuzzyMinSim: FLOAT,
phraseSlop: INT,
boost: FLOAT
}

ARGUMENT TYPES:

  • BOOL: true | false
  • INT: integer eg 5
  • FLOAT: float eg 1.2
  • STRING: text eg "foo"
  • DATETIME: dates and times
    eg "2010-02-31T13:30:45", "2010-02-31", "13:30:45"
  • VALUE: BOOL | INT | FLOAT | STRING | DATETIME

thanks

clint

--
Web Announcements Limited is a company registered in England and Wales,
with company number 05608868, with registered address at 10 Arvon Road,
London, N5 1PR.

Hello Shay,
Did you finally publish the formal spec off the DSL on the elastic.co website ?
If so, can you give a link ?

Thanks