How to deal with elasticsearch range Beetween 2 dates - php

I have the following mapping:
'contract' => [
'type' => 'nested',
'include_in_parent' => true,
'properties' => [
'started_at' => ['type' => 'date', 'format' => 'yyyy-MM-dd'],
'ended_at' => ['type' => 'date', 'format' => 'yyyy-MM-dd'],
],
],
I'm trying to write a query that searches for all active contracts; a contract is active when now is between started_at and anded_at, or started_at < now if the contract is undetermined (ended_at is null).
my try was the following, but still doesn't handle both the cases:
'bool' => [
'must' => [
['range' => ['applications.contract.started_at' => ['lte' => 'now']]],
['range' => ['applications.contract.ended_at' => ['gte' => 'now']]],
],
],
Any hint would be awesome, thanks folks!

When you have "nullable" field as "ended_at" you need to combine "range" and "must_not" into "should" because elasticsearch does not index NULL value (as a result it's a missing field)
So your query will look something like this:
{
"query": {
"bool": {
"must": [
{
"range": {"applications.contract.started_at": {"lte": "now"}}
},
"should": [
{
"range": {
"applications.contract.ended_at": {"gte": "now"}
}
},
{
"bool": {
"must_not": {
"exists": "applications.contract.ended_at"
}
}
}
]
}
}
}
also, I've noticed that you are using "nested" documents so the query above must be wrapped into a nested query
{
"bool": {
"must": {
"nested": {
"path": "contract",
"query": {
"bool": {
"must": [
{
"range": {"applications.contract.started_at": {"lte": "now"}}
}
],
"should": [
{
"range": {
"applications.contract.ended_at": {"gte": "now"}
}
},
{
"bool": {
"must_not": {
"exists": {"field": "applications.contract.ended_at"}
}
}
}
]
}
}
}
}
}
}

Related

Combine OR, AND and IN operators in Elasticsearch query

I am very new to the elasticsearch and I need to prepare the query which combines OR, AND and IN operators.
What I want to achieve is having something like this in SQL:
SELECT * FROM tableWHERE (field_1 = 'foo' AND field_2 IN(1,2,3) ) OR ('field_1 = 'bar' AND field_2 IN(2, 3, 4) );
I am using elastic with PHP and have started with something like this:
'query' => [
'bool' => [
'should' => [
[
'match' => [
'field_1' => 'foo',
],
],
[
'match' => [
'field_1' => 'bar',
],
],
],
],
],
However, I cannot add query parameters to achive my desired result. Can you please help me with that?
You need to combine bool/must/should query clauses. For IN operator you can use terms query in elasticsearch
Try out this below query
{
"query": {
"bool": {
"should": [
{
"bool": {
"must": [
{
"match": {
"field_1": "foo"
}
},
{
"terms": {
"field_2": [
1,
2,
3
]
}
}
]
}
},
{
"bool": {
"must": [
{
"match": {
"field_1": "bar"
}
},
{
"terms": {
"field_2": [
2,
3,
4
]
}
}
]
}
}
]
}
}
}

not able to get array in the correct shape

I am trying to create an elasticsearch query and for that I need to get my array in a particular shape but I am not able to get it.
desired output
"query": {
"bool": {
"must": {
"bool": {
"must": [
"match": {
"active": 1
},
"bool": {
"should": [
{
"match": {
"workspace_type.keyword": "lounge"
}
},
{
"match": {
"workspace_type.keyword": " cafe"
}
}
]
}
]
}
}
}
}
My source code
$query = [
'query' => [
'bool' => [
'must' => [
'bool' => [
'must' => []
]
]
]
]
];
$active_query = [
'match' => [
"active" => 1
]
];
$query['query']['bool']['must']['bool']['must'][] = $active_query;
$workspace_type_query = [
'match' => [
"workspace_type.keyword" => "lounge"
]
];
$workspace_type_object = (object) $workspace_type_query;
$query['query']['bool']['must']['bool']['must']['bool']['should'][] = $workspace_type_object;
only issue with this is I am not able to get must[] (the one above match and active ) and it was either coming as an indexed object like
{
"0": {
"match": {
"active": 1
}
}
}
or just an object like this
{
"match": {
"active": 1
}
}
but both these cases are not acceptable for the elasticsearch query that I am trying to generate .. any assistance would be highly appreciated.
I think the extra index that you create for must is wrong.
When you change it to
$query['query']['bool']['must']['bool']['must'] = $active_query;
it seems to work.
The result is
{
"query": {
"bool": {
"must": {
"bool": {
"must": {
"match": {
"active": 1
}
}
}
}
}
}
}

No results once implementing an analyzer in Elasticsearch

I am needing to ignore the apostrophe with indexed results so that searching for "Johns potato" will show results for "John's potato"
I was able to get the analyzer accepted but now I return no search results. Does anyone see something obvious that I am missing?
$params = [
'index' => $index,
'body' => [
'settings' => [
'number_of_shards' => 5,
'number_of_replicas' => 2,
'analysis' => [
"analyzer" => [
"my_analyzer" => [
"tokenizer" => "keyword",
"char_filter" => [
"my_char_filter"
]
]
],
"char_filter" => [
"my_char_filter" => [
"type" => "mapping",
"mappings" => [
"' => "
]
]
]
]
],
'mappings' => [
$type => [
'_source' => [
'enabled' => true
],
'properties' => [
'title' => [
'type' => 'text',
'analyzer' => 'my_analyzer'
],
'content' => [
'type' => 'text',
'analyzer' => 'my_analyzer'
]
]
]
]
]
];
I did find out that removing the analyzer from my field mappings allowed results to reappear, but I get no results the second I add the analyzer.
Here's an example query that I make.
{
"body": {
"query": {
"bool": {
"must": {
"multi_match": {
"query": "apples",
"fields": [
"title",
"content"
]
}
},
"filter": {
"terms": {
"site_id": [
"1351",
"1349"
]
}
},
"must_not": [
{
"match": {
"visible": "false"
}
},
{
"match": {
"locked": "true"
}
}
]
}
}
}
}
Probably, what you really want, is to use the english analyzer that is provided. The standard analyzer which is the default will tokenize on whitespace and some punctuation, but will leave apostrophes alone. The english analyzer can stem and remove stop words since the language is known.
Here is the standard analyzer's output, where you can see "john's":
POST _analyze
{
"analyzer": "standard",
"text": "John's potato"
}
{
"tokens": [
{
"token": "john's",
"start_offset": 0,
"end_offset": 6,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "potato",
"start_offset": 7,
"end_offset": 13,
"type": "<ALPHANUM>",
"position": 1
}
]
}
And here is the english analyzer where you can see the 's is removed. The stemming will allow "John's", "Johns", and "John" to all match the document.
POST _analyze
{
"analyzer": "english",
"text": "John's potato"
}
{
"tokens": [
{
"token": "john",
"start_offset": 0,
"end_offset": 6,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "potato",
"start_offset": 7,
"end_offset": 13,
"type": "<ALPHANUM>",
"position": 1
}
]
}

Elasticsearch. Nested query for nested in nested

My mapping is (part of it):
$index = [
"mappings" => [
"goods" => [
"dynamic_templates"=> [
[
"iattribute_id"=> [
"match_mapping_type"=> "string",
"match"=> "attribute_id",
"mapping"=> [
"type"=> "integer"
]
]
],
[
"iattribute_value"=> [
"match_mapping_type"=> "string",
"match"=> "attribute_value",
"mapping"=> [
"type"=> "string",
"index" => "not_analyzed"
]
]
]
],
"properties" => [
...
"individual_attributes" => [
"type" => "nested",
"properties" => [
"template_id" => ["type" => "integer"],
"attributes_set" => [
"type" => "nested",
"properties" => [
"attribute_id" => ["type" => "integer"],
"attribute_value" => ["type" => "string", "index" => "not_analyzed"]
]
]
]
]
...
]
]
]
];
How can I query attribute_id and attribute_value? They are nested inside nested. I can't understand how to specify path to fields.
I've composed query but it doesn't work.
GET /index/type/_search
{
"query" : {
"nested" : {
"path" : "individual_attributes.attributes_set",
"score_mode" : "none",
"filter": {
"bool": {
"must": [
{
"term" : {
"individual_attributes.attributes_set.attribute_id": "20"
}
},
{
"term" : {
"individual_attributes.attributes_set.attribute_value": "commodi"
}
}
]
}
}
}
}
}
Try this:
{
"query": {
"nested": {
"path": "individual_attributes",
"score_mode": "none",
"filter": {
"nested": {
"path": "individual_attributes.attributes_set",
"query": {
"bool": {
"must": [
{
"term": {
"individual_attributes.attributes_set.attribute_id": "20"
}
},
{
"term": {
"individual_attributes.attributes_set.attribute_value": "commodi"
}
}
]
}
}
}
}
}
}
}

AND filter elastic search PHP

I'm trying to have multiple queries in ELASTIC SEARCH However I just want to have an operator AND to separate them as condition, for example as in SQL,
SELECT * FROM table where P=1 AND Q=2
In such query, we find only those results which will fulfil both conditions. In my case, P=1 is my first query and Q=2 is my second one.
How can I get the results for such query. Im using PHP.
Here's my Code:
// MY QUERY 1
$query["bool"]["must"][]["multi_match"] = array(
"query"=>$string,
"operator" => "and",
"fields" => array("firstname", "lastname")
);
// MY QUERY 2
$query["bool"]["must"][]["multi_match"] = array(
'query' =>$string2,
'fields' => array("firstname1", "firstname2")
);
// SEARCH
$return = $client->search(
array(
'index' => 'my_index',
'type' => 'typ',
'body' => array(
'query' => $query,
'size' => 100,
),
)
);
You can use a filter query with an and operator like this. Try it out.
{
"filter": {
"and": [
{
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "searchTerm1",
"fields": [
"firstname",
"lastname"
]
}
}
]
}
}
},
{
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "searchTerm2",
"fields": [
"firstname1",
"firstname2"
]
}
}
]
}
}
}
]
}
}

Categories