Home > Enterprise >  Filtering for top hits aggregation not working as expected
Filtering for top hits aggregation not working as expected

Time:11-17

On a parent document I have a list of nested items, which I need to query separately (including paging, sorting and so on). I think the Top hits aggregation is what I need. Unfortunately I don't get the filtering in a way I would expect:

DELETE /test_index

PUT /test_index?pretty=true
{
  "mappings": {
    "properties": {
      "items": {
        "dynamic": false,
        "properties": {
          "text": {
            "type": "keyword"
          },
          "visible": {
            "type": "boolean"
          }
        },
        "type": "nested"
      }
    }
  }
}

POST /test_index/_doc?pretty=true&refresh=wait_for
{
  "description": "Parent 1",
  "items": [
    {
      "text": "Foo A",
      "visible": true
    },
    {
      "text": "Foo invisible",   // <-- this one is found, though visible should be true
      "visible": false
    }
  ]
}

POST /test_index/_doc?pretty=true&refresh=wait_for
{
  "description": "Parent 2",
  "items": [
    {
      "text": "Foo B",
      "visible": true
    }
  ]
}

POST /test_index/_doc?pretty=true&refresh=wait_for
{
  "description": "Parent 3",
  "items": [
    {
      "text": "Foo",     // <-- this one is not found, which is correct
      "visible": false
    }
  ]
}

POST /test_index/_search?pretty=true&typed_keys=true
{
  "aggs": {
    "by_items": {
      "aggs": {
        "top_item_hits": {
          "top_hits": {
            "from": 0,
            "size": 20,
            "sort": [
              {
                "items.text": {
                  "order": "asc"
                }
              }
            ]
          }
        }
      },
      "nested": {
        "path": "items"
      }
    }
  },
  "query": {
    "nested": {
      "path": "items",
      "query": {
        "term": {
          "items.visible": {
            "value": true
          }
        }
      }
    }
  },
  "size": 0,
  "_source": false
}

As mentioned in the comment, one item is found which I wouldn't expect. I know it is related to the sibling in the list which is found, but how can I change the request to filter out all invisible items?

CodePudding user response:

Great progress so far!! You're almost there!

You simply need to add the same filter you have in the query part in the nested aggregation as well and top_hits must be a sub-aggregation of that filter aggregation, like this:

{
  "aggs": {
    "by_items": {
      "nested": {
        "path": "items"
      },
      "aggs": {
        "filter": {                 <--- add this filter
          "term": {
            "items.visible": {
              "value": true
            }
          }
        },
        "aggs": {
          "top_item_hits": {        <--- top_hits should be nested below
            "top_hits": {
              "from": 0,
              "size": 20,
              "sort": [
                {
                  "items.text": {
                    "order": "asc"
                  }
                }
              ]
            }
          }
        }
      }
    }
  },
  "query": {
    "nested": {
      "path": "items",
      "query": {
        "term": {
          "items.visible": {
            "value": true
          }
        }
      }
    }
  },
  "size": 0,
  "_source": false
}
  • Related