🏡 Home 📖 Chapter Home 👈 Prev 👉 Next

⚡  ElasticsearchBook is crafted by Jozef Sorocin (🟢 Book a consulting hour) and powered by:

An interesting application of partial text matching is an autocomplete with a dropdown:

[Courtesy of Ant Design](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/c8d2b8d5-c29b-4d2a-9ec6-f30bb60e4c9a/Screen_Recording_2021-02-04_at_14.31.18.mov)

Courtesy of Ant Design

People are unlikely to input the whole tag and will want only the tags that contain their input. These days we even expect auto-correct and natural language understanding but that's a topic for a different chapter — maybe even a whole new (hand)book 😉 .

Use Case

Each of my documents contains an array of tags:

{
  ...
  "tags": ["Race", "Racing", "Mountain Bike", "Horizontal"],
  ...
},
{
  ...
  "tags": ["Tracey Chapman", "Silverfish", "Blue"],
  ...
},
{
  ...
  "tags": ["Surfing", "Race", "Disgrace"],
  ...
}

If the user types race, I only want to return Race, Tracey Chapman, and Disgrace — i.e. only the tags that contain my query string. What's more, I want this to be as fast as possible because it's fed through an autocomplete.

Approach

Option #1: Regex

Now, extracting and grouping the contents of textual arrays is usually done through a terms aggregation:

POST tags_index/_search
{
  "size": 0,
  "aggs": {
    "topics": {
      "terms": {
        "field": "tags",
        "size": 10
      }
    }
  }
}

This'll give us all tags separately. But we want to filter them and luckily, there's the include parameter which supports regex:

POST tags_index/_search
{
  "size": 0,
  "aggs": {
    "topics": {
      "terms": {
        "field": "tags",
        "include": ".*[Rr][Aa][Cc][Ee].*", 
        "size": 10
      }
    }
  }
}

There are two problems with this regex-based approach though:

  1. it's awfully slow