I have the below query in which I want to get the search term "Schwarz" either in the name field or the message field. The language must be Austrian and the status type should be equal to the provided list. I'm getting the following exception and I can't figure out why:
QueryParsingException[[my_test_index] [_na] query malformed, no field after start_object]; }]",
{
"query": {
"filtered": {
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{
"term": {
"name": "Schwarz"
}
},
{
"term": {
"message": "Schwarz"
}
}
],
"minimum_should_match": 1
}
},
{
"terms": {
"status_type": [
"1",
"2",
"3",
"4",
"5",
"6",
"7"
]
}
},
{
"term": {
"language": "Austrian"
}
}
]
}
}
}
},
"sort": [
{
"total": {
"order": "desc"
}
}
]
}
Here is the query without the filter that still works:
{
"query": {
"filtered": {
"query": {
"bool": {
"should": [
{
"match": {
"standard_analyzed_name": "Schwarz"
}
},
{
"match": {
"standard_analyzed_message": "Schwarz"
}
}
],
"must": [
{
"terms": {
"buzzsumo_status_type": [
"1",
"2",
"3",
"4",
"5",
"6",
"7"
]
}
},
{
"term": {
"language": "Austrian"
}
}
]
}
}
}
},
"sort": [
{
"total_interactions": {
"order": "desc"
}
}
]
}
In a filtered query you MUST have a filter part, which is not present here. I would suggest rewriting it like this, i.e. move the terms and term parts into the filter part:
{
"query": {
"filtered": {
"query": {
"bool": {
"should": [
{
"term": {
"name": "Schwarz"
}
},
{
"term": {
"message": "Schwarz"
}
}
],
"minimum_should_match": 1
}
},
"filter": {
"bool": {
"must": [
{
"terms": {
"status_type": [
"1",
"2",
"3",
"4",
"5",
"6",
"7"
]
}
},
{
"term": {
"language": "Austrian"
}
}
]
}
}
}
},
"sort": [
{
"total": {
"order": "desc"
}
}
]
}
An alternative is to not use the filtered query and simply write it like this:
{
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{
"term": {
"name": "Schwarz"
}
},
{
"term": {
"message": "Schwarz"
}
}
],
"minimum_should_match": 1
}
},
{
"terms": {
"status_type": [
"1",
"2",
"3",
"4",
"5",
"6",
"7"
]
}
},
{
"term": {
"language": "Austrian"
}
}
]
}
},
"sort": [
{
"total": {
"order": "desc"
}
}
]
}
Related
The original query looks like this
{
"query": {
"bool": {
"must": [
{
"has_parent": {
"parent_type": "doc",
"query": {
"bool": {
"must": [
{
"terms": {
"id": [
713
]
}
},
{
"range": {
"created": {
"lte": "now/d"
}
}
},
{
"range": {
"expires": {
"gte": "now/d"
}
}
}
]
}
}
}
},
{
"term": {
"doc_type": "item"
}
},
{
"bool": {
"should": [
{
"term": {
"have_prices": true
}
},
{
"term": {
"is_folder": true
}
}
]
}
}
],
"must_not": {
"exists": {
"field": "folder"
}
}
}
},
"sort": [
{
"is_folder": {
"order": "desc"
}
},
{
"title_low.order": {
"order": "asc"
}
}
],
"size": 1000
}
And I got some result
"hits": {
"total": 19,
"max_score": null,
"hits": [
{
"_index": "prices",
"_type": "doc",
"_id": "item-6800004",
"_score": null,
"_routing": "1",
"_source": {
"id": 6800004,
"id_pricedoc": 713,
"title": "\"водка №1\" 1",
"title_low": "\"водка №1\" 1",
"supplier": {
"id": 7831,
"type": null
},
"supplier_nom": {
"id": 1375697,
"market_nom": {
"id": null
},
"codes": null,
"sup_code": "7a6713a5-73c1-3acb-9b62-9e38b2314dce",
"manufacturer": {
"id": null,
"title": null
}
},
"is_folder": false,
"folder": null,
"path": null,
"pricedoc_created": "2016-03-21",
"prices": [
{
"currency": "RUR",
"id_offer": 15735967,
"id_prcknd": 167,
"value": "391.50"
}
],
"have_prices": true,
"market": {
"title": null,
"uuid": null,
"folder": null,
"path": null
},
"_join_field_name": "doc_type",
"doc_type": {
"name": "item",
"parent": "doc-713"
}
},
"sort": [
0,
"\"водка №1\" 1"
]
}
Now I also would like get result where "id_prcknd": 167
Modified query looks like this
{
"query": {
"bool": {
"must": [
{
"has_parent": {
"parent_type": "doc",
"query": {
"bool": {
"must": [
{
"terms": {
"id": [
713
]
}
},
{
"range": {
"created": {
"lte": "now/d"
}
}
},
{
"range": {
"expires": {
"gte": "now/d"
}
}
}
]
}
}
}
},
{
"term": {
"doc_type": "item"
}
},
{
"bool": {
"should": [
{
"term": {
"have_prices": true
}
},
{
"term": {
"is_folder": true
}
}
]
}
}
],
"must_not": {
"exists": {
"field": "folder"
}
}
},
"nested": {
"path": "prices",
"query": {
"bool": {
"must": [
{
"match": {
"prices.id_prcknd": 167
}
}
]
}
}
},
"sort": [
{
"is_folder": {
"order": "desc"
}
},
{
"title_low.order": {
"order": "asc"
}
}
],
"size": 1000
}}
But I got an error Elasticsearch malformed query, expected [END_OBJECT] but found [FIELD_NAME]
Where am I wrong?
I wanna match objects where "id_prcknd": 167
The stackoverflow says the I post mostly the code, but it's because of large queries in elastic search.
What Elasticsearch was trying to say is that it did not expect to see other keys but bool in the dictionary (the value under "query").
In your example code you have something like this:
{
"query": {
"bool": {
"must": [
{...},
{...},
{...}
],
"must_not": {...},
"nested": {...}, // this should go under "must"
"sort": [...], // this should go on the same level as "query"
"size": 1000 // this should go on the same level as "query"
}
}
"bool" here refers to a bool query, and should be the only key in the dictionary.
What you should do is to move "nested" into its own dictionary and the fourth element of the must array (if I understood the logic of what you are trying to achieve correctly). Please note that also "sort" and "size" should be moved - this time, to the same level as "query".
The full query will look like this:
{
"query": {
"bool": {
"must": [
{
"has_parent": {
"parent_type": "doc",
"query": {
"bool": {
"must": [
{
"terms": {
"id": [
713
]
}
},
{
"range": {
"created": {
"lte": "now/d"
}
}
},
{
"range": {
"expires": {
"gte": "now/d"
}
}
}
]
}
}
}
},
{
"term": {
"doc_type": "item"
}
},
{
"bool": {
"should": [
{
"term": {
"have_prices": true
}
},
{
"term": {
"is_folder": true
}
}
]
}
},
{
"nested": {
"path": "prices",
"query": {
"bool": {
"must": [
{
"match": {
"prices.id_prcknd": 167
}
}
]
}
}
}
}
],
"must_not": {
"exists": {
"field": "folder"
}
}
}
},
"sort": [
{
"is_folder": {
"order": "desc"
}
},
{
"title_low.order": {
"order": "asc"
}
}
],
"size": 1000
}
Your json is incorrect: Error:Expecting closing } at end[Code 22, Structure 183]
Use a json validator (https://jsonformatter.curiousconcept.com/) for example.
Here is my sample dataset,
{
"parent":[
{
"name":"John Doe 1",
"age":"100 year",
"sex":"male",
"child":[
{
"name":"Jane Doe 1",
"height":100.00,
"width":100.00
},
{
"name":"Jane Doe 2",
"height":100.00,
"width":100.00
}
]
},
{
"name":"John Doe 2",
"age":"100 year",
"sex":"male",
"child":[
{
"name":"Jane Doe 3",
"height":100.00,
"width":100.00
},
{
"name":"Jane Doe 4",
"height":100.00,
"width":100.00
}
]
}
]
}
And my definition:
{
"settings": {
"index": {
"analysis": {
"analyzer": {
"default": {
"type": "simple"
}
}
}
}
},
"mappings": {
"_doc": {
"properties": {
"parent": {
"type": "nested",
"properties": {
"name": {
"type": "keyword"
},
"age": {
"type": "text"
},
"sex": {
"type": "text"
},
"child": {
"type": "nested",
"properties": {
"name": {
"type": "text"
},
"height": {
"type": "float"
},
"width": {
"type": "float"
}
}
}
}
}
}
}
}
}
I'm using the following query to look for matches in the parent.name property and can get highlights.
{
"query": {
"bool": {
"should": [
{
"nested": {
"inner_hits": {
"highlight": {
"fields": {
"parent.name": {}
},
"number_of_fragments": 0,
"pre_tags": [
"<span>"
],
"post_tags": [
"</span>"
]
}
},
"path": "parent",
"query": {
"bool": {
"must": [
{
"match": {
"parent.name": {
"query": "John",
"fuzziness": "AUTO:3,6",
"prefix_length": "0"
}
}
}
]
}
}
}
}
],
}
},
"_source": ["parent"],
"sort": [
{
"_score": {
"order": "desc"
}
},
{
"createdOn": {
"order": "desc"
}
}
]
}
Is there a way to get inline highlights for the matches in the child.name properties also so that it would be easy to find exactly which element of that corresponding array got matched?
For example, for the given sample data, if I search by "Doe", I'm expecting to get 6 hits, whereas if I search by "Jane", I would get only 4.
You can simply add another nested query clause inside you top level should.
Here's how your query should look:
{
"query": {
"bool": {
"should": [
{
"nested": {
"inner_hits": {
"highlight": {
"fields": {
"parent.name": {}
},
"number_of_fragments": 0,
"pre_tags": [
"<span>"
],
"post_tags": [
"</span>"
]
}
},
"path": "parent",
"query": {
"bool": {
"must": [
{
"match": {
"parent.name": {
"query": "John Doe 1"
}
}
}
]
}
}
}
},
{
"nested": {
"inner_hits": {
"highlight": {
"fields": {
"parent.child.name": {}
},
"number_of_fragments": 0,
"pre_tags": [
"<span>"
],
"post_tags": [
"</span>"
]
}
},
"path": "parent.child",
"query": {
"bool": {
"must": [
{
"match": {
"parent.child.name": {
"query": "Jane Doe 1"
}
}
}
]
}
}
}
}
],
"minimum_should_match": 1
}
},
"_source": ["parent"],
"sort": [
{
"_score": {
"order": "desc"
}
},
{
"createdOn": {
"order": "desc"
}
}
]
}
I have an index with the following documents:
{
"first_name": "f1",
"last_name": "l1",
"location": "SF",
"vehicle": {
"type": "car",
"color": "red"
}
}
{
"first_name": "f2",
"last_name": "l2",
"location": "SF",
"vehicle": {
"type": "motorcycle",
"color": "blue"
}
}
{
"first_name": "f3",
"last_name": "l3",
"location": "SF",
"vehicle": {
"type": "bicycle",
"color": "green"
}
}
{
"first_name": "f4",
"last_name": "l4",
"location": "CA",
"vehicle": {
"type": "motorcycle",
"color": "green"
}
}
{
"first_name": "f5",
"last_name": "l5",
"location": "SF"
}
The vehicle document is a nested type.
I would like to filter results:
SELECT WHERE location=SF AND (vehicle.type=car OR
vehicle.type=airplane OR not-exists(vehicle.type)
I could not find a way to do it.
Is there a way to execute such a filter on Elasticsearch?
Thank you.
This query might be helpful.
POST IndexName/Type/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"location": {
"value": "sf"
}
}
},
{
"bool": {
"should": [
{
"terms": {
"vehicle.type": [
"car",
"airplane"
]
}
},
{
"bool": {
"must_not": {
"exists": {
"field": "vehicle.type"
}
}
}
}
]
}
}
]
}
}
}
If you want to search location by case sensitive then use below query. I have used location.keyword for match case sensitive.
POST IndexName/Type/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"location.keyword": {
"value": "SF"
}
}
},
{
"bool": {
"should": [
{
"terms": {
"vehicle.type": [
"car",
"airplane"
]
}
},
{
"bool": {
"must_not": {
"exists": {
"field": "vehicle.type"
}
}
}
}
]
}
}
]
}
}
}
I found a way to do it, it is a bit complex but:
GET indextests/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"location": "SF"
}
},
{
"bool": {
"should": [
{
"nested": {
"path": "vehicle",
"query": {
"terms": {
"vehicle.type": ["car", "bicycle"]
}
}
}
},
{
"bool": {
"must_not": [
{
"nested": {
"path": "vehicle",
"query": {
"bool": {
"should": [
{
"bool": {
"must": [
{
"exists": {
"field": "vehicle.type"
}
}
]
}
}
]
}
}
}
}
]
}
}
]
}
}
]
}
}
}
My object in ES looks like:
{
"_index": "myIndex",
"_type": "myType",
"_id": "75fd98d2-eca7-4a94-9dd8-1cc2c9b1fbbf",
"_version": 2,
"found": true,
"_source": {
"account_id": "100",
"import_ids": [
"4f4eef42-5493-464e-ac08-68a3a25a01fb"
],
"accept": "html",
"deleted_at": null,
"signup_form_ids": [
{
"timestamp": "2015-11-23T20:08:11.604000",
"signup_form_id": "1234"
}
],
"mailing_status": "active",
"group_ids": [
"0eddd2c0-ce70-4eb7-bcd8-9e41e41ac0b3"
],
"confirmed_opt_in_at": null,
"fields": [
{
"text_value": "My Company",
"name": "company"
},
{
"text_value": "Foo",
"name": "first-name"
},
{
"text_value": "Bar",
"name": "last_name"
},
{
"text_value": "555-555-5555",
"name": "phone"
}
],
"created_at": "2015-11-23T19:20:15.889000",
"last_modified_at": "2015-11-23T20:08:11.604000",
"bounce_count": 0,
"opted_out_at": null,
"archived_at": null,
"email": "example#example.com",
"opt_out_mailing_id": "None"
}
}
I am trying to run write a query that gives me all hits where the signup_form_ids.timestamp are lte now-7d/d. I'm looking at https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-range-query.html#ranges-on-dates but unsure how to structure the query
This is what I have so far:
{
"query": {
"nested": {
"path": "signup_form_ids",
"bool": {
"must": [
{
"range": {
"timestamp" {
"lte": "now-7d/d"
}
}
}
]
}
},
"bool": {
"must": [
{
"bool": {
"must": []
}
},
{
"match": {
"account_id": "100"
}
},
{
"filtered": {
"filter": {
"missing": {
"field": "deleted_at"
}
}
}
}
]
}
},
"size": 500,
"from": 0
}
There are several things wrong here, and it's not entirely obvious which ones are artifacts of you adjusting your query to post here.
First, you're missing a colon after "timestamp" in your query. Also, you have an empty inner "bool". And your "range" query is inside a needless "bool". Also your "filtered" clause is redundant and you can just use the "filter" inside it.
But the main problems are that 1) your "nested" query needs to be inside your "bool" if you want all the conditions to apply, 2) your "nested" "range" filter needs to specify the full path to "timestamp" and 3) the "bool" inside your "nested" clause needs to be in a "filter".
So, making minimal adjustments to make the query work, the following query returns the document you posted (I changed the "lte" to "gte" so the document you posted would be returned, otherwise it doesn't match the query, yet):
POST /test_index/_search
{
"query": {
"bool": {
"must": [
{
"bool": {
"must": []
}
},
{
"match": {
"account_id": "100"
}
},
{
"filtered": {
"filter": {
"missing": {
"field": "deleted_at"
}
}
}
},
{
"nested": {
"path": "signup_form_ids",
"filter": {
"bool": {
"must": [
{
"range": {
"signup_form_ids.timestamp": {
"gte": "now-7d/d"
}
}
}
]
}
}
}
}
]
}
},
"size": 500,
"from": 0
}
If I clean it up to remove all the redundancies, I end up with:
POST /test_index/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"account_id": "100"
}
},
{
"missing": {
"field": "deleted_at"
}
},
{
"nested": {
"path": "signup_form_ids",
"filter": {
"range": {
"signup_form_ids.timestamp": {
"gte": "now-7d/d"
}
}
}
}
}
]
}
},
"size": 500,
"from": 0
}
Here is some code I used to play around with it:
http://sense.qbox.io/gist/ee96042c0505dfb07199b919d134b2a20c5a66fd
Say I had this document:
{
"_index": "food",
"_type": "recipes",
"_id": "AU2LjsMLOuShTUj_LBrT",
"_score": 1,
"_source": {
"name": "granola bars",
"ingredients": [
{
"name": "butter",
"quantity": 4
},
{
"name": "granola",
"quantity": 6
}
]
}
}
Using the following filter matches this document fine:
POST /food/recipes/_search
{
"query": {
"filtered": {
"query": {
"match_all": { }
},
"filter": {
"nested": {
"path": "ingredients",
"filter": {
"bool": {
"must": [
{
"terms": {
"ingredients.name": [
"butter",
"granola"
]
}
}
]
}
}
}
}
}
}
}
However it will also match documents that have additional ingredients.
How can I query so that it will only match documents that only have the ingredients butter and granola?
You need a "double negative", so to speak. You want to match parent documents that have nested docs that match your query, and no nested documents that don't match your query.
To test I set up the following index:
PUT /test_index
{
"settings": {
"number_of_shards": 1
},
"mappings": {
"doc": {
"properties": {
"ingredients": {
"type": "nested",
"properties": {
"name": {
"type": "string"
},
"quantity": {
"type": "long"
}
}
},
"name": {
"type": "string"
}
}
}
}
}
And added these two documents:
PUT /test_index/doc/1
{
"name": "granola bars",
"ingredients": [
{
"name": "butter",
"quantity": 4
},
{
"name": "granola",
"quantity": 6
}
]
}
PUT /test_index/doc/2
{
"name": "granola cookies",
"ingredients": [
{
"name": "butter",
"quantity": 5
},
{
"name": "granola",
"quantity": 7
},
{
"name": "milk",
"quantity": 2
},
{
"name": "sugar",
"quantity": 7
}
]
}
Your query returns both the documents. For the purposes of this question, to make it easier to understand, I first simplified your query a little:
POST /test_index/doc/_search
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"nested": {
"path": "ingredients",
"filter": {
"terms": {
"ingredients.name": [
"butter",
"granola"
]
}
}
}
}
}
}
}
Then I added an outer "bool" with two "nested" filters. One is the filter you originally had inside a "must", and the second is the opposite of the filter you had (so it will match nested documents that do NOT contain those terms), inside a "must_not":
POST /test_index/doc/_search
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"bool": {
"must": [
{
"nested": {
"path": "ingredients",
"filter": {
"terms": {
"ingredients.name": [
"butter",
"granola"
]
}
}
}
}
],
"must_not": [
{
"nested": {
"path": "ingredients",
"filter": {
"not": {
"filter": {
"terms": {
"ingredients.name": [
"butter",
"granola"
]
}
}
}
}
}
}
]
}
}
}
}
}
This returns only the one doc:
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "test_index",
"_type": "doc",
"_id": "1",
"_score": 1,
"_source": {
"name": "granola bars",
"ingredients": [
{
"name": "butter",
"quantity": 4
},
{
"name": "granola",
"quantity": 6
}
]
}
}
]
}
}
Here is all the code I used for testing it:
http://sense.qbox.io/gist/e5fd0c35070fb329d40ad342b3198695e6f52d3a