Only return nested child objects with deep nesting

Hi, very new to Elasticsearch so please forgive the potentially stupid question which is surely related either to my query or to my mapping.

In short, I have index "cases" which is the parent of nested object stages, which in turn has nested objects caseManagement, contacts, and persons. I want to do a search for a term in (long) narrative field cases.stages.contacts.narrative, for example "abuse." I want to return the cases that match (this works), then only the stages that match (this does not), and within the stages that match, only the contacts with matching narrative. Instead, I get the full matching case, with all the stages and contacts, when there is even one narrative that matches the search.

I vaguely understand that the use of inner_hits is probably relevant here, but I am certain I have fouled up either the mapping or the query, possibly because of the multiple levels of nesting. Thank you in advance for any help!

Mapping:

{
  "cases": {
    "aliases": {},
    "mappings": {
      "properties": {
        "caseId": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "caseName": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "endDate": {
          "type": "date"
        },
        "stages": {
          "type": "nested",
          "properties": {
            "caseManagement": {
              "type": "nested",
              "properties": {
                "assignedDate": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "employeeId": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "firstName": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "lastName": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "role": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "unassignedDate": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                }
              }
            },
            "contacts": {
              "type": "nested",
              "properties": {
                "contactedPersons": {
                  "properties": {
                    "contacted": {
                      "type": "boolean"
                    },
                    "discussed": {
                      "type": "boolean"
                    },
                    "personId": {
                      "type": "text",
                      "fields": {
                        "keyword": {
                          "type": "keyword",
                          "ignore_above": 256
                        }
                      }
                    },
                    "privateConversation": {
                      "type": "boolean"
                    }
                  }
                },
                "contactid": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "dateTime": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "employeeid": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "narrative": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                }
              }
            },
            "persons": {
              "type": "nested",
              "properties": {
                "dob": {
                  "type": "date"
                },
                "firstName": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "lastName": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "personId": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "relationship": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "stagePersonId": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "stageRole": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                }
              }
            },
            "stageCode": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "stageId": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            }
          }
        },
        "startDate": {
          "type": "date"
        },
        "status": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        }
      }
    },
    "settings": {
      "index": {
        "routing": {
          "allocation": {
            "include": {
              "_tier_preference": "data_content"
            }
          }
        },
        "number_of_shards": "1",
        "provided_name": "cases",
        "creation_date": "1706184519426",
        "number_of_replicas": "1",
        "uuid": "FDN5ylzRQAGaf-do2mw6yA",
        "version": {
          "created": "8500003"
        }
      }
    }
  }
}

Query:

GET /cases/_search
{
    "query":{
        "nested": {
            "path": "stages",
            "query": {
                "nested": {
                  "inner_hits": {},
                  "path": "stages.contacts",
                  "query": {
                    "term": {
                      "stages.contacts.narrative": "abuse"
                    }
                  }
                }
            }
        }
    }
}

Thank you kindly in advance for helping this ignorant soul out!

Hi,

you can use the inner_hits feature of Elasticsearch. This feature allows you to return only the nested documents that match your query, instead of the entire document.

Here's how you can modify your query:

GET /cases/_search
{
  "query": {
    "nested": {
      "path": "stages",
      "query": {
        "nested": {
          "path": "stages.contacts",
          "query": {
            "match": {
              "stages.contacts.narrative": "abuse"
            }
          },
          "inner_hits": {}
        }
      },
      "inner_hits": {}
    }
  }
}

Regards

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.