ElasticSearch query sub-objects - elasticsearch

I wandered through the docs a lot today, but can't find the answer; probably because I'm new to Elastic and don't really know the entire ES-terminology yet.
Say I have a books type containing a bunch of, well - books. Each book has a nested author.
{
"name": "Me and Jane",
"rating": "10",
"author": {
"name": "John Doe",
"alias":"Mark Twain"
}
}
Now, I know we can query the authors fields like this:
"match": {
"author.name": "Doe"
}
But what if I want to search across all the author fields? I tried author._all, which doesn't work.

Another approach is multi_match with wildcard field names: https://www.elastic.co/guide/en/elasticsearch/guide/current/multi-match-query.html#_using_wildcards_in_field_names
Something like this, I think:
"query": {
"nested": {
"path": "author",
"query": {
"multi_match": {
"query": "doe",
"fields": [
"author.*"
]
}
}
}
}
UPDATE: full sample provided
PUT /books
{
"mappings": {
"paper": {
"properties": {
"author": {
"type": "nested",
"properties": {
"name": {
"type": "string"
},
"alias": {
"type": "string"
}
}
}
}
}
}
}
POST /books/paper/_bulk
{"index":{"_id":1}}
{"author":[{"name":"john doe","alias":"doe"},{"name":"mark twain","alias":"twain"}]}
{"index":{"_id":2}}
{"author":[{"name":"mark doe","alias":"john"}]}
{"index":{"_id":3}}
{"author":[{"name":"whatever","alias":"whatever"}]}
GET /books/paper/_search
{
"query": {
"nested": {
"path": "author",
"query": {
"multi_match": {
"query": "john",
"fields": [
"author.*"
]
}
}
}
}
}
Result is:
"hits": {
"total": 2,
"max_score": 0.5906161,
"hits": [
{
"_index": "books",
"_type": "paper",
"_id": "2",
"_score": 0.5906161,
"_source": {
"author": [
{
"name": "mark doe",
"alias": "john"
}
]
}
},
{
"_index": "books",
"_type": "paper",
"_id": "1",
"_score": 0.5882852,
"_source": {
"author": [
{
"name": "john doe",
"alias": "doe"
},
{
"name": "mark twain",
"alias": "twain"
}
]
}
}
]
}

You can use Query String Query, The example:
{
"query": {
"query_string": {
"fields": ["author.*"],
"query": "doe",
"use_dis_max": true
}
}
}

Related

Search in multiple fields in ElasticSearch returns more results than expected

I'm trying to perform a search by country, or city or both using ElasticSearch.
When I perform a search by country using USA as the search term, I get these results, which are correct.
email
country
city
mike#example.com
USA
Portland
You Can Also
USA
Chicago
The query looks like so:
{
"body": {
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{
"match": {
"country": {
"query": "USA",
"operator": "and"
}
}
}
]
}
}
]
}
}
}
}
The problem is that if I want to also search by city using the term Portland I'm expecting to get only one result
email
country
city
mike#example.com
USA
Portland
but I get both results again, just like when I'm only searching by country.
The query for both fields looks like this:
{
"body": {
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{
"match": {
"country": {
"query": "USA",
"operator": "and"
}
}
}
]
}
},
{
"bool": {
"should": [
{
"match": {
"country": {
"query": "USA",
"operator": "and"
}
}
},
{
"match": {
"city": {
"query": "Portland",
"operator": "and"
}
}
}
]
}
}
]
}
}
}
}
What am I doing wrong?
There is no need to use multiple bool/should clause and operator (with match query), in your case.
Adding a working example
Search by country
{
"query": {
"bool": {
"must": {
"match": {
"country": {
"query": "USA"
}
}
}
}
}
}
Search Result:
"hits": [
{
"_index": "67676851",
"_type": "_doc",
"_id": "1",
"_score": 0.18232156,
"_source": {
"email": "mike#example.com",
"country": "USA",
"city": "Portland"
}
},
{
"_index": "67676851",
"_type": "_doc",
"_id": "2",
"_score": 0.18232156,
"_source": {
"email": "You Can Also",
"country": "USA",
"city": "Chicago"
}
}
]
Search by city:
{
"query": {
"bool": {
"must": {
"match": {
"city": {
"query": "Portland"
}
}
}
}
}
}
Search Result:
"hits": [
{
"_index": "67676851",
"_type": "_doc",
"_id": "1",
"_score": 0.6931471,
"_source": {
"email": "mike#example.com",
"country": "USA",
"city": "Portland"
}
}
]
Search by city and country:
{
"query": {
"bool": {
"must": [
{
"match": {
"city": "Portland"
}
},
{
"match": {
"country": "USA"
}
}
]
}
}
}
Search Result:
"hits": [
{
"_index": "67676851",
"_type": "_doc",
"_id": "1",
"_score": 0.8754687,
"_source": {
"email": "mike#example.com",
"country": "USA",
"city": "Portland"
}
}
]

ElasticSearch compound queries

My index data is
{
"first_name":"Kevin",
"last_name":"John",
"job": "IT"
}
{
"first_name":"John",
"last_name":"Thimothy",
"job": "Accountant"
}
{
"first_name":"Eric",
"last_name":"Villa",
"job": "Driver"
}
{
"first_name":"John",
"last_name":"Villa",
"job": "Student"
}
I am not sure if anyone could help me to build a query to get data that have first_name or last_name as John and have a job as IT or Student.
You need to use a combination of the bool/must/should clause
Search Query:
{
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{
"match": {
"first_name": "John"
}
},
{
"match": {
"last_name": "John"
}
}
]
}
},
{
"bool": {
"should": [
{
"match": {
"job": "IT"
}
},
{
"match": {
"job": "student"
}
}
]
}
}
]
}
}
}
Search Result will be
"hits": [
{
"_index": "66982646",
"_type": "_doc",
"_id": "1",
"_score": 2.4079456,
"_source": {
"first_name": "Kevin",
"last_name": "John",
"job": "IT"
}
},
{
"_index": "66982646",
"_type": "_doc",
"_id": "4",
"_score": 1.89712,
"_source": {
"first_name": "John",
"last_name": "Villa",
"job": "Student"
}
}
]

How to access elasticsearch nested objects

I tried to get my head wrapped around nested queries but I can't get this to work.
I have 2 items in ES that look like this
{
"_index": "catalog",
"_type": "products",
"_source": {
"product": {
"ean": "abc",
"features": {
"Product Type": "DVD player",
},
"color": "Black",
"manufacturer": "Sony",
"sitedetails": [
{
"name": "amazon.com",
"sku": "zzz",
"url": "http://www.amazon.com/dp/zzz"
}
],
"category": "Portable DVD Players"
}
}
},
{
"_index": "catalog",
"_type": "products",
"_source": {
"product": {
"ean": "def",
"features": {
"Product Type": "MP3 player",
},
"color": "Black",
"manufacturer": "LG",
"sitedetails": [
{
"name": "amazon.com",
"sku": "aaa",
"url": "http://www.amazon.com/dp/aaa"
}
],
"category": "MP3 Players"
}
}
}
2 questions:
What is the curl to get sku = zzz?
What is the curl to get both items on a search for "players"?
tnx!
Heyy bro, lets do the magic.
First , you need an mapping including your nested objects, like this
curl -XPUT "http://192.168.99.100:9200/catalog" -d'
{
"mappings": {
"products": {
"properties": {
"product": {
"type": "nested",
"properties": {
"features": {
"type":"nested"
},
"sitedetails": {
"type": "nested"
}
}
}
}
}
}
}'
After that, lets insert your data (change your Product Type to product_type)
curl -XPOST "http://192.168.99.100:9200/catalog/products" -d'
{
"product": {
"ean": "abc",
"features": {
"product_type": "DVD player"
},
"color": "Black",
"manufacturer": "Sony",
"sitedetails": [
{
"name": "amazon.com",
"sku": "zzz",
"url": "http://www.amazon.com/dp/zzz"
}
],
"category": "Portable DVD Players"
}
}'
Now, lets do the query
curl -XPOST "http://192.168.99.100:9200/catalog/products/_search" -d'
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "product.features",
"query": {
"match": {
"product.features.product_type": "player"
}
}
}
},
{
"nested": {
"path": "product.sitedetails",
"query": {
"match": {
"product.sitedetails.sku": "zzz"
}
}
}
}
]
}
}
}'
And the response will be:
"hits": {
"total": 1,
"max_score": 1.4054651,
"hits": [
{
"_index": "catalog",
"_type": "products",
"_id": "AVM_fcYgvVoSi3OfqPTX",
"_score": 1.4054651,
"_source": {
"product": {
"ean": "abc",
"features": {
"Product Type": "DVD player"
},
"color": "Black",
"manufacturer": "Sony",
"sitedetails": [
{
"name": "amazon.com",
"sku": "zzz",
"url": "http://www.amazon.com/dp/zzz"
}
],
"category": "Portable DVD Players"
}
}
}
]
}
Hope it help :D
Use:
curl 'http://localhost:9200/catalog/products/_search?q=sku:"zzz"&pretty=true'
curl 'http://localhost:9200/catalog/products/_search?q=sku:*&pretty=true'. like my thinking, you want to get data within sku:"zzz" and sku:"aaa".
Referer:
http://joelabrahamsson.com/elasticsearch-101/
http://www.elasticsearchtutorial.com/elasticsearch-in-5-minutes.html

How to query for inner_hits against grandparents in multi-generational setup

So I've set up my Elasticsearch store according to this: https://www.elastic.co/guide/en/elasticsearch/guide/current/grandparents.html
PUT /company
{
"mappings": {
"country": {},
"branch": {
"_parent": {
"type": "country"
}
},
"employee": {
"_parent": {
"type": "branch"
}
}
}
}
POST /company/country/_bulk
{ "index": { "_id": "uk" }}
{ "name": "UK" }
{ "index": { "_id": "france" }}
{ "name": "France" }
POST /company/branch/_bulk
{ "index": { "_id": "london", "parent": "uk" }}
{ "name": "London Westmintster" }
{ "index": { "_id": "liverpool", "parent": "uk" }}
{ "name": "Liverpool Central" }
{ "index": { "_id": "paris", "parent": "france" }}
{ "name": "Champs Élysées" }
PUT /company/employee/1?parent=london&routing=uk
{
"name": "Alice Smith",
"dob": "1970-10-24",
"hobby": "hiking"
}
This query works fine and returns Alice as expected, but no inner_hits:
POST /company/employee/_search
{
"query": {
"has_parent": {
"type": "branch",
"query": {
"term": {"_id": "london"}
},
"inner_hits": {}
}
}
}
But this query doesn't return any inner_hits:
POST /company/employee/_search
{
"query": {
"has_parent": {
"type": "branch",
"query": {
"has_parent": {
"type": "country",
"query": {
"term": {"_id": "uk"}
}
},
"inner_hits": {}
}
}
}
}
I thought it would return Alice, but it doesn't. How do I find all employees whose country is uk?
Note that the example query on elastic.co doesn't return any inner_hits either. Here's the query:
GET /company/country/_search
{
"query": {
"has_child": {
"type": "branch",
"query": {
"has_child": {
"type": "employee",
"query": {
"match": {
"hobby": "hiking"
}
},
"inner_hits": {}
}
}
}
}
}
I got zero inner_hits.
This is currently an outstanding with inner_hits.
You can add on the issue here: https://github.com/elastic/elasticsearch/issues/11118

How to highlight date fields in Elasticsearch?

My mapping:
"mappings": {
"my_type": {
"properties": {
"birthDate": {
"type": "date",
"format": "dateOptionalTime"
},
"name": {
"type": "string"
}
}
}
}
My search query:
GET my_index/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"name": "babken"
}
},
{
"term": {
"birthDate": {
"value": "1999-01-01"
}
}
}
]
}
},
"highlight": {
"fields": {
"*": {}
}
}
}
However in the response body, only the name field is highlighted, even though the birthDate field has matched as well:
"hits": [
{
"_index": "my_index",
"_type": "my_type",
"_id": "1a82fbb4-1268-42b9-9999-ef932f67a114",
"_score": 12.507131,
"_source": {
"name": "babken",
"birthDate": "1999-01-01",
},
"highlight": {
"name": [
"<em>babken</em>"
]
}
}
...
How can I make the birthDate field appear in "highlight" results as well if it has matched?
I'm using Elasticsearch 1.6
You would need to change the the type to string to enable highlighting.
Bare minimum requirement for a field to be enabled for highlighting is that it should be string type.
The following issue has little more discussion about it.

Resources