Home > Enterprise >  Creating an aggregation combined with condition in ElasticSearch
Creating an aggregation combined with condition in ElasticSearch

Time:11-29

Given the ElasticSearch document below:

{
    "_id": "3330481",
    "_type": "user",
    "_source": {
        "id": "3330481",
        "project": "Cool_Project_One"
    }
}

I'm building a UI component that will auto suggest to the user all the values in "project" field base on his text input

For example:
As the user types "Cool" i would like to show him all the values from the "project" field that starts with "Cool"

I've create this aggregation:

"aggs": {
    "projects": {
        "terms": {
            "field": "project",
            "size": 2
        }
    }
}

which returns me a list with all the values for the project field, but i can't understand how should i find only the values that are matching to a certain expression.
I've found this answer that shows how to add filter, but it seems that the filter returns only exact matches as i tried to do that:

{
    "aggs": {
        "projects": {
            "filter": {
                "term": {
                    "project": "Cool"
                }
            },
            "aggs": {
                "terms": {
                    "field": "project",
                    "size": 2
                }
            }
        }
    }
}

And it didn't worked.

Any help would be appreciated

CodePudding user response:

Some notes:

  1. term query will look for exact matches (casing included, if you want something more flexible you can use a regular "match" query
  2. In general, you want to add the filter in the query, no aggregations
  3. You can use aggregations to group by category type fields, but you can use regular queries to match against title type fields

I would suggest to use a suggestion field type for this, to also capture prefixes (proj in project por example).

https://www.elastic.co/guide/en/elasticsearch/reference/current/search-as-you-type.html

I just seen you have _type defined, so probably you are using an old version of Elasticsearch, and search_as_you_type is relatively new. I will add some examples with both query and aggs:

Mappings for search_as_you_type, text, and keyword fields :

PUT test_suggestions  
{
  "mappings": {
    "properties": {
      "project": {
        "type": "text",
        "fields": {
          "suggestions": {
            "type": "search_as_you_type"
          },
          "keyword": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

Indexing document

POST test_suggestions/_doc
{
  "project": "Cool Project"
}

search_as_you_type query, supports prefixes out of the box:

GET test_suggestions/_search
{
  "query": {
    "multi_match": {
      "query": "coo",
      "type": "bool_prefix",
      "fields": [
        "project",
        "project._2gram",
        "project._3gram"
      ]
    }
  },
  "aggs": {
    "project_categories": {
      "terms": {
        "field": "project.keyword",
        "size": 10
      }
    }
  }
}

Regular query, case insensitive and you can write just a portion of the field and will work

GET test_suggestions/_search
{
  "query": {
    "match": {
      "project": "Cool"
    }
  },
  "aggs": {
    "project_categories": {
      "terms": {
        "field": "project.keyword",
        "size": 10
      }
    }
  }
}

Bonus: prefix search without search_as_you_type or setting up ngrams:

GET test_suggestions/_search
{
  "query": {
    "match_phrase_prefix": {
      "project": "coo"
    }
  },
  "aggs": {
    "project_categories": {
      "terms": {
        "field": "project.keyword",
        "size": 10
      }
    }
  }
}
  • Related