I want to query similary follow's SQL :
select * from talbe where id=cityid
Who know how to implement in es ?
thanks for your answer !
You can do this with a script filter like this:
POST /table/_search
{
"query": {
"bool": {
"filter": {
"script": {
"script": "doc.id.value == doc.cityid.value"
}
}
}
}
}
Related
I would like to construct an elasticsearch query in which I can search for a term and on-the-fly compute a new field for each found document, which is calculated based on some existing fields as well as the query term. Is this possible?
For example, let's say in my EL query I am searching for documents which have the keyword "amsterdam" in the "text" field.
"filter": [
{
"match_phrase": {
"text": {
"query": "amsterdam"
}
}
}]
Now I would also like to have a script field in my query, which computes some value based on other fields as well as the query.
So far, I have only found how to access the other fields of a document though, using doc['someOtherField'], for example
"script_fields" : {
"new_field" : {
"script" : {
"lang": "painless",
"source": "if (doc['citizens'].value > 10000) {
return "large";
}
return "small";"
}
}
}
How can I integrate the query term, e.g. if I wanted to add to the if statement "if the query term starts with a-e"?
You're on the right track but script_fields are primarily used to post-process your documents' attributes — they won't help you filter any docs because they're run after the query phase.
With that being said, you can use scripts to filter your documents through script queries. Before you do that, though, you should explore alternatives.
In other words, scripts should be used when all other mechanisms and techniques have been exhausted.
Back to your example. I see three possibilities off the top of my head.
Match phrase prefix queries as a group of bool-should subqueries:
POST your-index/_search
{
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{
"match_phrase_prefix": {
"text_field": "a"
}
},
{
"match_phrase_prefix": {
"text_field": "b"
}
},
{
"match_phrase_prefix": {
"text_field": "c"
}
},
... till the letter "e"
]
}
}
]
}
}
}
A regexp query:
POST your-index/_search
{
"query": {
"bool": {
"must": [
{
"regexp": {
"text_field": "[a-e].+"
}
}
]
}
}
}
Script queries using .charAt comparisons:
POST your-index/_search
{
"query": {
"bool": {
"must": [
{
"script": {
"script": {
"source": """
char c = doc['text_field.keyword'].value.charAt(0);
return c >= params.gte.charAt(0) && c <= params.lte.charAt(0);
""",
"params": {
"gte": "a",
"lte": "e"
}
}
}
}
]
}
}
}
If you're relatively new to ES and would love to see real-world examples, check out my recently released Elasticsearch Handbook. One chapter is dedicated to scripting and as it turns out, you can achieve a lot with scripts (if of course executed properly).
is there a way of creating a field in document within a painless script
if it does not exists?
i'm using something like:
if(!ctx._source.tags.contains(....)
but tags field may not be exists at document
can it be done?
thanks.
If you plan to use the _update_by_query API, I'd recommend you to do something like:
POST your_index/_update_by_query
{
"query": {
"bool": {
"must_not": {
"exists": {
"field": "tags"
}
}
}
},
"script": {
"source": "ctx._source.tags = ''"
}
}
Otherwise, just using painless, you can do something like:
{
"script": {
"source": """
if(ctx._source.tags == null) {
ctx._source.tags = null;
}
"""
}
}
I need to build an exclusive bucketing aggregation in Elasticsearch (ie. the documents are assigned to the FIRST bucket to meet the criterion, not ALL buckets that meet it as the filters might overlap - this is the same behavior as a CASE WHEN THEN ELSE in SQL environments). Currently I am using a Filters Aggregation coupled with a Bool Query/Filter to achieve what I want. The idea is to use the "must" and "must_not" parts of the "Bool Query" where the "must" is my filter and the "must_not" is the collection of all the other filters that have already been used previously. An example would be:
GET _search
{
"query":{"match_all":{}},
"size":0,
"aggs":{
"bin_1": {
"filter": {
"bool": {
"must": { <filter1> },
"must_not": { <empty> }
}
}
},
"bin_2": {
"filter": {
"bool": {
"must": { <filter2> },
"must_not": { <filter1> }
}
}
},
"bin_3": {
"filter": {
"bool": {
"must": { <filter3> },
"must_not": { <filter1>, <filter2> }
}
}
},
"bin_else": {
"filter": {
"bool": {
"must": { <empty> },
"must_not": { <filter1>, <filter2>, <filter3> }
}
}
}
}
}
In a relational approach, the same would be achieved by the CASE WHEN clause like so:
CASE WHEN <filter1> THEN <bin_1>
WHEN <filter2> THEN <bin_2>
WHEN <filter3> THEN <bin_3>
ELSE <bin_else>
END
The problem with this approach is that it gets slower and slower the more buckets I add (in my real case I even have nested buckets). Is there any language support for exclusive bucketing like this in Elastic? Or any other faster approach that would yield the same results?
Thank you!
I think the solution would be to Script fields. It would use the if else logic, so no extra conditions would be used. Just I do not know what kind of filter you are using but it should be possible to implement anything I think. I will write here an equivalent of
SELECT
CASE WHEN <filter1> THEN <bin_1>
WHEN <filter2> THEN <bin_2>
ELSE <bin_else>
END as binning
FROM SOMETHING
Implemented using script fields in painless language. As is described here:
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-script-fields.html
and painless here:
https://www.elastic.co/guide/en/elasticsearch/painless/5.6/painless-examples.html
GET _search
{
"query" : { "match_all": {} },
"script fields" : {
"binning" : {
"script" : {
"lang": "painless",
"source": "if (<filter>) {return <bin1>;} else if (<filter2>) {return <bin2>;} else {return <bin3>;}"
}
}
}
where the "filter" would be something like: doc['my_field'].value == "value1" where 'my_field' is the field that you use in the filter.
I'm new to elastic search. How to generate elastic search equivalent query for
select * from response where pnrno='sampleid'
I know we have to use 'filter' option in elastic search.but we do not need any ranking. (ranking can be constant) so how can I generate query for achieve this
you are correct , you can use filtered query with query clause empty and filters.Filtering a set of documents is to filter the sets upon which query acts to furthur filter/match and calculate relevance.Filters are like bool either match or reject(1/0).
{
"query": {
"filtered": {
"filter": {
"bool": {
"must": [{
"term": {
"FIELD": "VALUE"
}
}]
}
}
}
}
}
The usual way of achieving this is by using the constant_score query with an embedded term filter, like this:
{
"query": {
"constant_score": {
"filter": {
"term": {
"pnrno": "sampleid"
}
}
}
}
}
Let's say I have documents with the following fields:
{field1, field2, ... fieldn}
I need to run some queries where some of the conditions will require a comparison between two or more fields. like fieldX = fieldY
In standard SQL, an example could be:
SELECT * FROM Table1 WHERE farePrice>100 AND originRegion = destinationRegion
I'be been reading some documentation, and it looks "scripting" could be the only way to achieve this? Or are there any other options?
You can use the script filter -
{
"filtered": {
"query": {
"range": {
"farePrice": {
"gt": 100
}
}
},
"filter": {
"script": {
"script": "doc['originRegion'].value == doc['destinationRegion'].value"
}
}
}
}
You can find more information at here and here .