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
}
}
}
}
}
}
}
Related
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
]
}
}
]
}
}
]
}
}
}
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"}
}
}
}
]
}
}
}
}
}
}
I have severals doc and each doc contains nested fields and I want to order by position depending on thematic id
Document1 :
{
...
"thematics":[
{
"id": 1,
"position": 100
},
{
"id": 2,
"position": 1
}
]
}
Document2:
{
...
"thematics":[
{
"id": 2,
"position": 3
}
]
}
Document3:
{
...
"thematics":[
{
"id": 1,
"position": 40
}
]
}
For example, I would like to get only documents with thematics which contains id = 2
So I did something like that
$filter = BoolQuery();
...
$filter->addMust(new Query\Term(["thematics.id" => 2]));
And then when I want to apply sort method on position where thematic id = 2 and not something else.
I tried something like that :
case 'atp': // asc thematic position
$sort = [
"_score",
[
"thematics.position" => [
"order" => "asc",
"missing" => 0,
],
],
];
break;
...
$this->setSort($sort); // call parent method setSort(array()) of elastica-ruflin
Response example :
First case expected :
If I want to display all documents from thematic 1 the order must be :
Document3 then Document1.
Second case expected :
If I want to display all documents from thematic 2 the order must be :
Document1 then Document2.
But for now what I've got is :
- First case : Document3, Document1
- Second case : Document2, Document1
I'm guessing that it takes the first thematic's position of document1 to sort in both cases.
Edit :
I tried to change de mapping with a nested type
thematics:
type: nested
properties:
label: { type: string, index: not_analyzed }
slug: { index: not_analyzed }
name: { type: string, index: not_analyzed }
position: { type: integer }
id: { type: integer }
And the query but still not working
{
"query": {
"function_score": {
"query": {
"bool": {
"must": [
{
"bool": {
"must": [
{
"match_all": {}
}
]
}
}
],
"filter": [
{
"bool": {
"must": [
{
"term": {
"is_searchable": true
}
},
{
"nested": {
"path": "thematics",
"query": {
"term": {
"thematics.id": {
"value": 2
}
}
}
}
},
{
"exists": {
"field": "valuation"
}
},
{
"bool": {
"should": [
{
"bool": {
"must": [
{
"exists": {
"field": "valuation.translations.fr.title"
}
}
]
}
},
{
"bool": {
"must": [
{
"exists": {
"field": "valuation.translations.en.title"
}
}
]
}
},
{
"bool": {
"must": [
{
"term": {
"commercial_subcategory.category.id": 33
}
}
]
}
}
]
}
}
]
}
}
]
}
},
"boost_mode": "multiply",
"functions": [
{
"field_value_factor": {
"field": "booster",
"modifier": "square"
}
}
]
}
},
"sort": [
"_score",
{
"thematics.position": {
"order": "asc",
"missing": 0,
"mode": "min",
"nested_filter": {
"term": {
"thematics.id": {
"value": 2
}
}
}
}
}
]
}
Edit2: I get around the problem.
I changed my mapping so each document looks like that :
{
...
"thematics":[
"1": {
"id": 1,
"position": 100
},
"2": {
"id": 2,
"position": 1
}
]
}
And then I apply a Bool Query must / Exists Filter on "thematics.".$thematicId
And finally, my sort method looks like this :
case 'atp': // asc thematic position
$sort = [
"_score",
[
"thematics." . $thematicId . ".position" => [
"order" => "asc",
"missing" => 0,
],
],
];
break;
...
$this->setSort($sort); // call parent method setSort(array()) of elastica-ruflin
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"
}
}
]
}
}
}
}
}
}
}
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"
]
}
}
]
}
}
}
]
}
}