Search on array elements in ElasticSearch - elasticsearch

Im trying to search two or more values on array and get only those ones that match with all words (AND CLAUSE)
Some example:
{ "name" : "Chevrolet",
"value" : [ "gasolina", "alcool", "diesel"]
}
{ "name" : "Fiat",
"value" : [ "eletrica", "alcool"]
}
{ "name" : "Honda",
"value" : [ "diesel", "gasolina"]
}
My mapping
{
"mappings": {
"cars": {
"properties": {
"name": {
"type": "string"
},
"GasType": {
"type": "nested",
"properties": {
"value": {
"type": "string"
}
}
}
}
}
}
}
Query:
{
"query": {
"nested": {
"path": "GasType",
"query": {
"bool": {
"must": [
{ "match": {"GasType.value": "gasolina"}},
{ "match": {"GasType.value": "diesel"}}
]
}
}
}
}
}
My return is always empty and if i change de query i have got all those that contains "Gasolina" or "diesel"
I need those that has "Gasolina" AND "diesel"

Your test data doesn't match the mapping of the index. In your test data I don't see the nested field name GasType. In any case, the following works for me just fine:
DELETE test
PUT test
{
"mappings": {
"cars": {
"properties": {
"name": {
"type": "string"
},
"GasType": {
"type": "nested",
"properties": {
"value": {
"type": "string"
}
}
}
}
}
}
}
POST test/cars/_bulk
{"index":{}}
{"name":"Chevrolet","GasType":{"value":["gasolina","alcool","diesel"]}}
{"index":{}}
{"name":"Fiat","GasType":{"value":["eletrica","alcool"]}}
{"index":{}}
{"name":"Honda","GasType":{"value":["diesel","gasolina"]}}
{"index":{}}
{"name":"Honda","GasType":{"value":["diesel"]}}
GET test/_search
{
"query": {
"nested": {
"path": "GasType",
"query": {
"bool": {
"must": [
{
"match": {
"GasType.value": "gasolina"
}
},
{
"match": {
"GasType.value": "diesel"
}
}
]
}
}
}
}
}

Related

Elasticseach wildcard query on nested types

I'm trying to run a wildcard query on a nested type in ElasticSearch. I have records with the following structure:
{
"field_1": "value_1",
"nested_field_1": [
{
"field_type": "some_field_type",
"field_value": "some_value"
},
{
"field_type": "another_field_type",
"field_value": "another_value"
}
]
}
I want to be able to run wildcard query on the nested_field, either on field_value or on field_type.
I can query for an exact match with this syntax:
"query": {
"nested": {
"path": "nested_field_1",
"query": {
"bool": {
"must": [
{
"match": {
"nested_field_1.field_value": "another_value"
}
}
]
}
}
}
}
}
But replacing the match with wildcard doesn't yield any results.
Any help would be welcome.
So I just tried your example and it gives me the result and used elasticsearch official wildcard query doc.
Index Def
{
"mappings": {
"properties": {
"field_1": {
"type": "text"
},
"nested_field_1" :{
"type" : "nested",
"properties" : {
"field_type" :{
"type" : "text"
},
"field_value" :{
"type" : "integer" --> created as interfere field
}
}
}
}
}
}
Index doc
{
"field_1": "value_1",
"nested_field_1": [
{
"field_type": "some_field_type",
"field_value": 20
},
{
"field_type": "another_field_type",
"field_value": 40
}
]
}
Wildcard search query
{
"query": {
"nested": {
"path": "nested_field_1",
"query": {
"bool": {
"must": [
{
"wildcard": { --> note
"nested_field_1.field_type": {
"value": "another_field_type"
}
}
}
]
}
}
}
}
}
Search result
"nested_field_1": [
{
"field_type": "some_field_type",
"field_value": 20
},
{
"field_type": "another_field_type",
"field_value": 40
}
]
}

Elasticsearch for index array element

Hi i want to search array element from index using elastic search query
{
"name": "Karan",
"address": [
{
"city": "newyork",
"zip": 12345
},
{
"city": "mumbai",
"zip": 23456
}]
}}
when i am trying to search using match query it does not work
{
"query": {
"bool": {
"must": [
{
"match": {
"address.city": "newyork"
}
}
]
}
}
}
when i access simple feild like "name": "Karan" it works, there is only issue for array element.
Because nested objects are indexed as separate hidden documents, we can’t query them directly. Instead, we have to use the nested query to access them:
GET /my_index/blogpost/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"title": "eggs"
}
},
{
"nested": {
"path": "comments",
"query": {
"bool": {
"must": [
{
"match": {
"comments.name": "john"
}
},
{
"match": {
"comments.age": 28
}
}
]
}
}
}
}
]
}}}
See the docs
The way i followed..
Mapping :
{
"mappings": {
"job": {
"properties": {
"name": {
"type": "text"
},
"skills": {
"type": "nested",
"properties": {
"value": {
"type": "text"
}
}
}
}
}
}
Records
[{"_index":"jobs","_type":"job","_id":"2","_score":1.0,"_source":{"name":"sr soft eng","skills":[{"value": "java"}, {"value": "oracle"}]}},{"_index":"jobs","_type":"job","_id":"1","_score":1.0,"_source":{"name":"sr soft eng","skills":[{"value": "java"}, {"value": "oracle"}, {"value": "javascript"}]}},
search Query
{
"query": {
"nested": {
"path": "skills",
"query": {
"bool": {
"must": [
{ "match": {"skills.value": "java"}}
]
}
}
}
}
}

How to improve inner_hits in Elasticsearch

I have two ES_TYPEs in my_index
user
user_property
One is defined as parent (user) and another as child (user_property)
user_property has following mapping:
PUT /my_index/_mapping/user_property
{
"user_property": {
"properties": {
"name": {
"type": "keyword",
},
"value": {
"type": "keyword"
}
}
}
}
I want to get all users having some properties (say property1, property2) along with their properties value, so to do this I create following query with inner_hits but query response time is exponentially large with inner_hits.
GET /my_index/user/_search
{
"query": {
"bool": {
"must": [
{
"has_child": {
"type": "user_property",
"query": {
"bool": {
"must": [
{
"term": {
"name": "property1"
}
}
]
}
},
"inner_hits": {
"name": "inner_hits_1"
}
}
},
{
"has_child": {
"type": "user_property",
"query": {
"bool": {
"must": [
{
"term": {
"name": "property2"
}
}
]
}
},
"inner_hits": {
"name": "inner_hits_2"
}
}
}
]
}
}
}
Is there any way to reduce this time ?

Elasticsearch nested query and order by "hits"

Using Elasticsearch, I'm trying to search nested data and return the documents with the most "hits."
Relevant Example Data
POST myrecipes/recipe
{
"title": "Potato Salad",
"ingredients": [
{"name":"potato"},
{"name":"mayonaise"},
{"name":"mustard"},
{"name":"bacon"},
{"name":"onion"},
{"name":"parsley"}
]
}
POST myrecipes/recipe
{
"title": "Seared Scallops",
"ingredients": [
{"name":"scallops"},
{"name":"butter"},
{"name":"bacon"}
]
}
POST myrecipes/recipe
{
"title": "Tuna melt",
"ingredients": [
{"name":"tuna"},
{"name":"onion"},
{"name":"butter"},
{"name":"bacon"},
{"name":"mayonaise"},
{"name":"lettuce"},
{"name":"tomato"},
{"name":"bread"}
]
}
My Index
PUT myrecipes
{
"mappings": {
"recipe": {
"properties": {
"ingredients": {
"type": "nested",
"include_in_parent": true,
"properties": {
"name": {
"type": "string",
"fields": {
"untouched": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
}
}
}
}
}
My Search:
POST myrecipes/recipe/_search
{
"query": {
"nested": {
"path": "ingredients",
"query": {
"bool": {
"should": [
{
"match": {
"ingredients.name": {
"query": "bacon"
}
}
},
{
"match": {
"ingredients.name": {
"query": "butter"
}
}
}
]
}
}
}
}
}
The query returns
"Tuna melt", "Potato Salad", "Seared Scallops"
I'm hoping for:
"Seared Scallops", "Tuna melt", "Potato Salad"
Since there are two "hits" on "Seared scallops" and "Tuna Melt" (bacon and butter), and only one "hit" on "Potato Salad" (bacon).

Elasticsearch : search document with conditional filter

I have two documents in my index (same type) :
{
"first_name":"John",
"last_name":"Doe",
"age":"24",
"phone_numbers":[
{
"contract_number":"123456789",
"phone_number":"987654321",
"creation_date": ...
},
{
"contract_number":"123456789",
"phone_number":"012012012",
"creation_date": ...
}
]
}
{
"first_name":"Roger",
"last_name":"Waters",
"age":"36",
"phone_numbers":[
{
"contract_number":"546987224",
"phone_number":"987654321",
"creation_date": ...,
"expired":true
},
{
"contract_number":"87878787",
"phone_number":"55555555",
"creation_date": ...
}
]
}
Clients would like to perform a full text search. Okay no problem here
My problem :
In this full text search, sometimes user will search by phone_number. In this case there is a parameter like expired=true.
Example :
First client search request : "987654321" with expired absent or set to false
--> Result : Only first document
Second client search request : "987654321" with expired set to true
--> Result : The two documents
How can I achieve that ?
Here is my mapping :
{
"user": {
"_all": {
"auto_boost": true,
"omit_norms": true
},
"properties": {
"phone_numbers": {
"type": "nested",
"properties": {
"phone_number": {
"type": "string"
},
"creation_date": {
"type": "string",
"index": "no"
},
"contract_number": {
"type": "string"
},
"expired": {
"type": "boolean"
}
}
},
"first_name":{
"type": "string"
},
"last_name":{
"type": "string"
},
"age":{
"type": "string"
}
}
}
}
Thanks !
MC
EDIT :
I tried this query :
{
"query": {
"filtered": {
"query": {
"query_string": {
"query": "987654321",
"analyze_wildcard": "true"
}
},
"filter": {
"nested": {
"path": "phone_numbers",
"filter": {
"bool": {
"should":[
{
"bool": {
"must": [
{
"term": {
"phone_number": "987654321"
}
},
{
"missing": {
"field": "expired"
}
}
]
}
},
{
"bool": {
"must_not": [
{
"term": {
"phone_number": "987654321"
}
}
]
}
}
]
}
}
}
}
}
}}
But I get the two documents instead of get only the first one
You're very close. Try using a combination of must and should, where the must clause ensures the phone_number matches the search value, and the should clause ensures that either the expired field is missing or set to false. For example:
{
"query": {
"filtered": {
"query": {
"query_string": {
"query": "987654321",
"analyze_wildcard": "true"
}
},
"filter": {
"nested": {
"path": "phone_numbers",
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"term": {
"phone_number": "987654321"
}
}
],
"should": [
{
"missing": {
"field": "expired"
}
},
{
"term": {
"expired": false
}
}
]
}
}
}
}
}
}
}
}
}
I ran this query using your mapping and sample documents and it returned the one document for John Doe, as expected.

Resources