"[nested] failed to find nested object under path [steps]" - elasticsearch

I have mapped data into this schema:
curl -X PUT "localhost:9200/data?pretty" -H 'Content-Type: application/json' -d
'{
"settings":{
"number_of_shards":"1",
"number_of_replicas":"1"
},
"mappings":{
"properties":{
"routines":{
"type":"nested",
"properties":{
"title":{
"type":"text"
},
"sources":{
"type":"keyword"
},
"flags":{
"type":"keyword",
"null_value":"NULL"
},
"steps":{
"type":"nested",
"properties":{
"time":{
"type":"keyword"
},
"products":{
"type":"nested",
"properties":{
"name":{
"type":"text"
},
"link":{
"type":"keyword",
"null_value":"NULL"
},
"type":{
"type":"keyword",
"null_value":"NULL"
},
"ingredients":{
"type":"keyword",
"null_value":"NULL"
},
"flags":{
"type":"keyword",
"null_value":"NULL"
}
}
}
}
}
}
}
}
}
}'
Now, I am trying to search two fields data.title and data.steps.products.name with this query:
curl -X GET "localhost:9200/data/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"bool": {
"should": [
{
"nested": {
"path": "data",
"query": {
"nested": {
"path": "steps",
"query": {
"nested": {
"path": "products",
"query": {
"multi_match": {
"query": "XXX",
"fields": [
"name"
]
}
}
}
}
}
}
}
},
{"multi_match": {
"query": "XXX",
"fields": [
"data.title"
]
}
}
]
}
}
}'
It throws error that it failed to find path under step:
{
"error" : {
"root_cause" : [
{
"type" : "query_shard_exception",
"reason" : "failed to create query: [nested] failed to find nested object under path [steps]",
"index_uuid" : "SjQgt4BHStC_APsMnZk8BQ",
"index" : "data"
}
],
"type" : "search_phase_execution_exception",
"reason" : "all shards failed",
"phase" : "query",
"grouped" : true,
"failed_shards" : [
{
"shard" : 0,
"index" : "data",
"node" : "L1azdi09QxanYGnP-y0xbQ",
"reason" : {
"type" : "query_shard_exception",
"reason" : "failed to create query: [nested] failed to find nested object under path [steps]",
"index_uuid" : "SjQgt4BHStC_APsMnZk8BQ",
"index" : "data",
"caused_by" : {
"type" : "illegal_state_exception",
"reason" : "[nested] failed to find nested object under path [steps]"
}
}
}
]
},
"status" : 400
}
Could you help to find an error with mapping/query?
UPDATE:
My json data: https://jsonkeeper.com/b/PSVS

Have a look at the Elastic documentation for multi-level nested queries.
What you forgot in your query is the full path of the nested object in each sub-level nested query. (also, you used a data field not existing in the mapping, while you wanted to have routines instead)
So your query would look like
curl -X GET "localhost:9200/data/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"bool": {
"should": [
{
"nested": {
"path": "routines",
"query": {
"nested": {
"path": "routines.steps",
"query": {
"nested": {
"path": "routines.steps.products",
"query": {
"multi_match": {
"query": "XXX",
"fields": [
"routines.steps.products.name"
]
}
}
}
}
}
}
}
},
{"multi_match": {
"query": "XXX",
"fields": [
"routines.title"
]
}
}
]
}
}
}'
Anyhow, please reconsider whether it is a good idea to have multi-level nested fields in the first place, as they have a significant impact on performance. E.g., would having an index for routines, maybe with a data identifier, make sense?
Edit: added the full path to the multi-matched field of the first should block

Related

Place an Analyzer on a a specific array item in a nested object

I have the following mapping
"mappings":{
"properties":{
"name": {
"type": "text"
},
"age": {
"type": "integer"
},
"customProps":{
"type" : "nested",
"properties": {
"key":{
"type": "keyword"
},
"value": {
"type" : "keyword"
}
}
}
}
}
example data
{
"name" : "person1",
"age" : 10,
"customProps":[
{"hairColor":"blue"},
{"height":"120"}
]
},
{
"name" : "person2",
"age" : 30,
"customProps":[
{"jobTitle" : "software engineer"},
{"salaryAccount" : "AvGhj90AAb"}
]
}
so i want to be able to search for document by salary account case insensitive, i am also searching using wild card
example query is
{
"query": {
"bool": {
"should": [
{
"nested": {
"path": "customProps",
"query": {
"bool": {
"must": [
{ "match": { "customProps.key": "salaryAccount" } },
{ "wildcard": { "customProps.value": "*AvG*"
}
}
]}}}}]}}}
i tried adding analyzer with PUT using the following syntax
{
"settings":{
"index":{
"analysis":{
"analyzer":{
"analyzer_case_insensitive" : {
"tokenizer":"keyword",
"filter":"lowercase"
}
}
}
}
},
"mappings":{
"people":{
"properties":{
"customProps":{
"properties":{
"value":{
"type": "keyword",
"analyzer": "analyzer_case_insensitive"
}
}
}
}
}
}
}
im getting the following error
"type" : "mapper_parsing_exception",
"reason" : "Root mapping definition has unsupported parameters: [people: {properties={customProps={properties={value={analyzer=analyzer_case_insensitive, type=keyword}}}}}]"
any idea how to do the analyzer for the salary account object in the array when it exists?
Your use case is quite clear, that you want to search on the value of salaryAccount only when this key exists in customProps array.
There are some issues with your mapping definition :
You cannot define a custom analyzer for keyword type field, instead you can use a normalizer
Based on the mapping definition you added at the beginning of the question, it seems that you are using elasticsearch version 7.x. But the second mapping definition that you provided, in that you have added mapping type also (i.e people), which is deprecated in 7.x
There is no need to add the key and value fields in the index mapping.
Adding a working example with index mapping, search query, and search result
Index Mapping:
PUT myidx
{
"mappings": {
"properties": {
"customProps": {
"type": "nested"
}
}
}
}
Search Query:
You need to use exists query, to check whether a field exists or not. And case_insensitive param in Wildcard query is available since elasticsearch version 7.10. If you are using a version below this, then you need to use a normalizer, to achieve case insensitive scenarios.
POST myidx/_search
{
"query": {
"bool": {
"should": [
{
"nested": {
"path": "customProps",
"query": {
"bool": {
"must": [
{
"exists": {
"field": "customProps.salaryAccount"
}
},
{
"wildcard": {
"customProps.salaryAccount.keyword": {
"value": "*aVg*",
"case_insensitive": true
}
}
}
]
}
}
}
}
]
}
}
}
Search Result:
"hits" : [
{
"_index" : "myidx",
"_type" : "_doc",
"_id" : "2",
"_score" : 2.0,
"_source" : {
"name" : "person2",
"age" : 30,
"customProps" : [
{
"jobTitle" : "software engineer"
},
{
"salaryAccount" : "AvGhj90AAb"
}
]
}
}
]

Elasticsearch nested geo-shape query

Suppose I have the following mapping:
"mappings": {
"doc": {
"properties": {
"name": {
"type": "text"
},
"location": {
"type": "nested",
"properties": {
"point": {
"type": "geo_shape"
}
}
}
}
}
}
}
There is one document in the index:
POST /example/doc?refresh
{
"name": "Wind & Wetter, Berlin, Germany",
"location": {
"type": "point",
"coordinates": [13.400544, 52.530286]
}
}
How can I make a nested geo-shape query?
Example of usual geo-shape query from the documentation (the "bool" block can be skipped):
{
"query":{
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_shape": {
"location": {
"shape": {
"type": "envelope",
"coordinates" : [[13.0, 53.0], [14.0, 52.0]]
},
"relation": "within"
}
}
}
}
}
}
Example of a nested query is:
{
"query": {
"nested" : {
"path" : "obj1",
"score_mode" : "avg",
"query" : {
"bool" : {
"must" : [
{ "match" : {"obj1.name" : "blue"} },
{ "range" : {"obj1.count" : {"gt" : 5}} }
]
}
}
}
}
}
Now how to combine them? In the documentation it is mentioned that nested filter has been replaced by nested query. And that it behaves as a query in “query context” and as a filter in “filter context”.
If I try query for intersect with the point:
{
"query": {
"nested": {
"path": "location",
"query": {
"geo_shape": {
"location.point": {
"shape": {
"type": "point",
"coordinates": [
13.400544,
52.530286
]
},
"relation": "disjoint"
}
}
}
}
}
}
I still get back the document even if relation is "disjoint", so it's not correct. I tried different combinations, with "bool" and "filter", etc. but query is ignored, returning the whole index. Maybe it's impossible with this type of mapping?
Clearly I am missing something here. Can somebody help me out with that, please? Any help is greatly appreciated.

inner_hits does not work for nested filters when searching multiple indices

Elasticsearch version
Version: 6.2.2
I'm trying to search multiple indices which both have nested objects. To keep it simple I will use this example. In the query I use "inner_hits" property.
PUT /sales
{
"mappings": {
"_doc" : {
"properties" : {
"tags" : { "type" : "keyword" },
"comments" : {
"type" : "nested",
"properties" : {
"username" : { "type" : "keyword" },
"comment" : { "type" : "text" }
}
}
}
}
}
}
PUT /sales/_doc/1?refresh
{
"tags": ["car", "auto"],
"comments": [
{"username": "baddriver007", "comment": "This car could have better brakes"},
{"username": "dr_who", "comment": "Where's the autopilot? Can't find it"},
{"username": "ilovemotorbikes", "comment": "This car has two extra wheels"}
]
}
PUT /markets
{
"mappings": {
"_doc" : {
"properties" : {
"name" : { "type" : "keyword" },
"products" : {
"type" : "nested",
"properties" : {
"name" : { "type" : "keyword" },
"sku" : { "type" : "text" }
}
}
}
}
}
}
POST /sales,markets/_search
{
"query": {
"bool": {
"should": [
{
"bool": {
"should": [
{
"nested": {
"path": "comments",
"inner_hits": {
},
"ignore_unmapped": true,
"query": {
"match_all": {}
}
}
}]
}
},
{
"bool": {
"should": [
{
"nested": {
"path": "products",
"inner_hits": {
},
"ignore_unmapped": true,
"query": {
"match_all": {}
}
}
}
]
}
}
]
}
}
}
So this query gives an error
{
"error": {
"root_cause": [
{
"type": "illegal_state_exception",
"reason": "[match_all] no mapping found for type [comments]"
},
{
"type": "illegal_state_exception",
"reason": "[match_all] no mapping found for type [products]"
}
],
"type": "search_phase_execution_exception",
"reason": "all shards failed",
"phase": "query",
"grouped": true,
"failed_shards": [
{
"shard": 0,
"index": "markets",
"node": "-22psoQNRLa8_Y9GeHBXaw",
"reason": {
"type": "illegal_state_exception",
"reason": "[match_all] no mapping found for type [comments]"
}
},
{
"shard": 0,
"index": "sales",
"node": "-22psoQNRLa8_Y9GeHBXaw",
"reason": {
"type": "illegal_state_exception",
"reason": "[match_all] no mapping found for type [products]"
}
}
]
},
"status": 500
}
But when I add "ignore_unmapped": true inside each "inner_hits": { "ignore_unmapped": true } everything works fine. This is not implemented in NEST .net library.
Is it right to use "ignore_unmapped" inside "inner_hits", because I didn't find this as "inner_hits" property in the documentation ?
Is there any other solution in NEST for this to be done.
UPDATE:
I tried using operator overloading queries and I got
Func<SearchDescriptor<object>, ISearchRequest> search = s => s.Type<object>()
.Index(Indices.Index("sales", "markets"))
.AllTypes()
.Explain(false)
.Query(q => (q
.Nested(n => n
.IgnoreUnmapped(true)
.Path(Infer.Field<SaleDocument>(f => f.Comments))
.InnerHits(ih => ih
.Size(1)
)
.Query(q1 => q1
.MatchAll()
)
) && +q.Terms(t => t
.Field("_index")
.Terms(new[] { "sales" })
)
) || (q
.Nested(n => n
.IgnoreUnmapped(true)
.Path(Infer.Field<MarketDocument>(f => f.Products))
.InnerHits(ih => ih
.Size(1)
)
.Query(q1 => q1
.MatchAll()
)
) && +q.Terms(t => t
.Field("_index")
.Terms(new[] { "markets" })
)
)
);
This code created query
POST /sales,markets/_search
{
"from": 0,
"size": 10,
"explain": false,
"query": {
"bool": {
"should": [
{
"bool": {
"must": [
{
"nested": {
"query": {
"match_all": {}
},
"path": "comments",
"inner_hits": {
"size": 1
},
"ignore_unmapped": true
}
}
],
"filter": [
{
"terms": {
"_index": [
"sales"
]
}
}
]
}
},
{
"bool": {
"must": [
{
"nested": {
"query": {
"match_all": {}
},
"path": "products",
"inner_hits": {
"size": 1
},
"ignore_unmapped": true
}
}
],
"filter": [
{
"terms": {
"_index": [
"markets"
]
}
}
]
}
}
]
}
}
}
Which again gives error
{
"error": {
"root_cause": [
{
"type": "illegal_state_exception",
"reason": "[match_all] no mapping found for type [comments]"
},
{
"type": "illegal_state_exception",
"reason": "[match_all] no mapping found for type [products]"
}
],
"type": "search_phase_execution_exception",
"reason": "all shards failed",
"phase": "query",
"grouped": true,
"failed_shards": [
{
"shard": 0,
"index": "markets",
"node": "-22psoQNRLa8_Y9GeHBXaw",
"reason": {
"type": "illegal_state_exception",
"reason": "[match_all] no mapping found for type [comments]"
}
},
{
"shard": 0,
"index": "sales",
"node": "-22psoQNRLa8_Y9GeHBXaw",
"reason": {
"type": "illegal_state_exception",
"reason": "[match_all] no mapping found for type [products]"
}
}
]
},
"status": 500
}
As you say, it looks like inner_hits property is missing within NEST; I'll open an issue to add this for the next release now.
ignore_unmapped is the way to handle this when needing inner_hits. If you didn't need inner_hits, you could combine each nested query with a term query on the "_index" metadata field that targets the respective index name in each case, such that the nested query is run only against the indices that contain the target field.
This issue has been fixed in both places and will be available in some of the future releases of NEST or ElasticSearch.
NEST .net library by adding IgnoreUnmapped() method in InnerHits.
https://github.com/elastic/elasticsearch-net/issues/3132
Elastic Search by inherit ignore_unmapped in inner_hits from nested query ignore_unmapped property
https://github.com/elastic/elasticsearch/issues/29071

elasticsearch searching array field inside nested type

i am trying to filter my result using nested filter but i am getting incorrect result
here is my mapping info
{
"stock" : {
"mappings" : {
"clip" : {
"properties" : {
"description" : {
"type" : "string"
},
"keywords" : {
"type" : "nested",
"properties" : {
"category" : {
"type" : "string"
},
"tags" : {
"type" : "string",
"index_name" : "tag"
}
}
},
"tags" : {
"type" : "string",
"index_name" : "tag"
},
"title" : {
"type" : "string"
}
}
}
}
}
}
clip document data
{
"_index" : "stock",
"_type" : "clip",
"_id" : "AUnsTOBBpafrKleQN284",
"_score" : 1.0,
"_source":{
"title": "journey to forest",
"description": "this clip contain information about the animals",
"tags": ["birls", "wild", "animals", "roar", "forest"],
"keywords": [
{
"tags": ["spring","summer","autumn"],
"category": "Weather"
},
{
"tags": ["Cloudy","Stormy"],
"category": "Season"
},
{
"tags": ["Exterior","Interior"],
"category": "Setting"
}
]
}
i am trying to filter tags inside nested field 'keywords'
here is my query
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"nested": {
"path": "keywords",
"filter": {
"bool": {
"must": [
{
"terms": { "tags": ["autumn", "summer"] }
}
]
}
}
}
}
}
}
}
i am getting no result why ?
what's wrong with my query or schema please help
The above query is syntactically incorrect . You need to provide the full path to tags from root keywords in the term query i.e.keywords.tags
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"nested": {
"path": "keywords",
"filter": {
"bool": {
"must": [
{
"terms": { "keywords.tags": ["autumn", "summer"] }
}
]
}
}
}
}
}
}
}

ElasticSearch: Searching fields in nested arrays

I'm fairly new to ES and am using it for a new project of mine. Starting off, I have a simple mapping for a customer, which has a first and last name, and a list of payment information objects. If I were doing this in SQL, it would be something like a customer table, and a payment info table with a 1:many relationship.
Here's a simple example of what I'm trying to do: https://gist.github.com/anonymous/6109593
I'm hoping to find any customer based on any match in the nested array of paymentInfos, i.e. finding any users who've had a paymentInfo with billingZip 10101. This query returns no results, and I'm not sure why. Can anyone point me in the right direction as to why this query doesn't work, and if there are any changes I can make to either my query or mapping to have it return the user properly?
Thanks!
Nested fields should be searched using nested query:
echo "Deleting old ElasticSearch index..."
curl -XDELETE 'localhost:9200/arrtest'
echo
echo "Creating new ElasticSearch index..."
curl -XPUT 'localhost:9200/arrtest/?pretty=1' -d '{
"mappings" : {
"cust2" : {
"properties" : {
"firstName" : {
"type" : "string",
"analyzer" : "string_lowercase"
},
"lastName" : {
"type" : "string",
"analyzer" : "string_lowercase"
},
"paymentInfos": {
"properties": {
"billingZip": {
"type": "string",
"analyzer": "string_lowercase"
},
"paypalEmail": {
"type": "string",
"analyzer": "string_lowercase"
}
},
"type": "nested"
}
}
}
},
"settings" : {
"analysis" : {
"analyzer" : {
"uax_url_email" : {
"filter" : [ "standard", "lowercase" ],
"tokenizer" : "uax_url_email"
},
"string_lowercase": {
"tokenizer" : "keyword",
"filter" : "lowercase"
}
}
}
}
}
'
echo
echo "Index recreation finished"
echo "Inserting one record..."
curl -XPUT 'localhost:9200/arrtest/cust2/1' -d '{
"firstName": "john",
"lastName": "smith",
"paymentInfos": [{
"billingZip": "10101",
"paypalEmail": "foo#bar.com"
}, {
"billingZip": "20202",
"paypalEmail": "foo2#bar2.com"
}]
}
'
echo
echo "Refreshing index to make new records searchable"
curl -XPOST 'localhost:9200/arrtest/_refresh'
echo
echo "Searching for record..."
curl -XGET 'localhost:9200/arrtest/cust2/_search?pretty=1' -d '{
"sort": [],
"query": {
"bool": {
"should": [],
"must_not": [],
"must": [{
"nested": {
"query": {
"query_string": {
"fields": ["paymentInfos.billingZip"],
"query": "10101"
}
},
"path": "paymentInfos"
}
}]
}
},
"facets": {},
"from": 0,
"size": 25
}'
echo

Resources