The key to what you want to do is the ignore_unmapped
option of the nested query
. It tells Elasticsearch to ignore indexes where the nested path has not been mapped, rather than return an error for those indexes. You can make use of that to separately query indexes with and without a nested type.
Let's say you have two indexes. "my_index1" in which a nested type my_nested_object
has been mapped, and "my_index2" where it has not:
PUT my_index1
{
"mappings": {
"_doc": {
"properties": {
"my_nested_object": {
"type": "nested",
"properties": {
"foo": {
"type": "keyword"
}
}
},
"bar": {
"type": "keyword"
}
}
}
}
}
PUT my_index2
{
"mappings": {
"_doc": {
"properties": {
"bar": {
"type": "keyword"
}
}
}
}
}
Now, let's index a document in each of these two indexes:
PUT my_index1/_doc/1
{
"my_nested_object": {
"foo": "123"
},
"bar": "456"
}
PUT my_index2/_doc/2
{
"bar": "456"
}
We can now query across these two indexes using a nested query with ignore_unmapped
set to true
to silently ignore the index where I do not have a nested object my_nested_object
:
GET my_index1,my_index2/_search
{
"query": {
"nested": {
"path": "my_nested_object",
"ignore_unmapped": true,
"query": {
"match": {
"my_nested_object.foo": "123"
}
}
}
}
}
I can also do the reverse: query only those indexes that do not have a nested object my_nested_object
. I can use the exists
query for that, which I wrap in a bool
query's must_not
:
GET my_index1,my_index2/_search
{
"query": {
"bool": {
"must_not": [
{
"nested": {
"path": "my_nested_object",
"ignore_unmapped": true,
"query": {
"exists": {
"field": "my_nested_object"
}
}
}
}
],
"must": [
{
"match": {
"bar": "456"
}
}
]
}
}
}
Both queries can be combined to get your desired OR-like behavior by wrapping them in a bool
query's should
clause:
GET my_index1,my_index2/_search
{
"query": {
"bool": {
"should": [
{
"nested": {
"path": "my_nested_object",
"ignore_unmapped": true,
"query": {
"match": {
"my_nested_object.foo": "123"
}
}
}
},
{
"bool": {
"must_not": [
{
"nested": {
"path": "my_nested_object",
"ignore_unmapped": true,
"query": {
"exists": {
"field": "my_nested_object"
}
}
}
}
],
"must": [
{
"match": {
"bar": "456"
}
}
]
}
}
]
}
}
}
It's not pretty, but it works