# Elasticsearch Query for Exact Substring Matching with Spaces

**URL:** <https://discuss.elastic.co/t/elasticsearch-query-for-exact-substring-matching-with-spaces/361216>\
**Category:** Elasticsearch\
**Created:** [June 11, 2024, 6:12am UTC](https://discuss.elastic.co/t/elasticsearch-query-for-exact-substring-matching-with-spaces/361216 "2024-06-11T06:12:10Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Umang\_Kamdar](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/umang_kamdar/32/135201_2.png) [@Umang\_Kamdar](https://discuss.elastic.co/u/Umang_Kamdar)\
**Post date:** [June 11, 2024, 6:12am UTC](https://discuss.elastic.co/t/elasticsearch-query-for-exact-substring-matching-with-spaces/361216/1 "2024-06-11T06:12:10Z")

</div>

I'm trying to perform an exact substring match in Elasticsearch, including substrings that contain spaces. Here’s what I need:

1. Search for an exact substring within a larger text field.
2. The substring may contain spaces.
3. The substring may be a partial word and not necessarily a full word.
4. I want to match the substring exactly as it appears, not just individual terms.

I've tried the following approaches without success:

Wildcard Query:

```auto
{
  "query": {
    "wildcard": {
      "description": {
        "value": "*substring with spaces*",
        "case_insensitive": true
      }
    }
  }
}

```

Query String with Analyze Wildcard:

```auto
{
  "query": {
    "query_string": {
      "query": "*substring with spaces*",
      "fields": ["description"],
      "analyze_wildcard": true,
      "default_operator": "AND"
    }
  }
}

```

Neither approach returns the expected results when the substring contains spaces.

**Example:**

_ **Field** _: description

_ **Value** _: "quick brown fox"

_ **Substring** _ can be any of the followings - "quick brown fox", "ick br", "quick bro", "quick" or "brown f" etc and I still want it to match exactly.

How can I construct an Elasticsearch query to achieve exact substring matching, including spaces and partial words?

---

<div class="post-metadata">

**Author:** ![dadoonet](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/dadoonet/32/137187_2.png) [@dadoonet](https://discuss.elastic.co/u/dadoonet)\
**Post date:** [June 11, 2024, 7:20am UTC](https://discuss.elastic.co/t/elasticsearch-query-for-exact-substring-matching-with-spaces/361216/2 "2024-06-11T07:20:41Z")

</div>

Welcome!

You could try the following strategy: [N-gram tokenizer | Elasticsearch Guide [8.14] | Elastic](https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-ngram-tokenizer.html)

---

<div class="post-metadata">

**Author:** ![Umang\_Kamdar](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/umang_kamdar/32/135201_2.png) [@Umang\_Kamdar](https://discuss.elastic.co/u/Umang_Kamdar)\
**Post date:** [June 11, 2024, 7:54am UTC](https://discuss.elastic.co/t/elasticsearch-query-for-exact-substring-matching-with-spaces/361216/3 "2024-06-11T07:54:50Z")

</div>

Thanks for the reply @dadoonet.  
Would this still be helpful even if i dont know what may be the length of my description? I mean how can i decide on the min-max grams? The input can be just a letter(like just 'q') or it may be the whole sentence(like 'quick brown fox') or may be just some random substring (like 'own fo').

In any of the cases I would always want the exact matching and all records that are matched should be in the result set. I also dont want any scoring as such, just all the results which match the given substring.

---

<div class="post-metadata">

**Author:** ![dadoonet](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/dadoonet/32/137187_2.png) [@dadoonet](https://discuss.elastic.co/u/dadoonet)\
**Post date:** [June 11, 2024, 9:33am UTC](https://discuss.elastic.co/t/elasticsearch-query-for-exact-substring-matching-with-spaces/361216/4 "2024-06-11T09:33:47Z")

</div>

Another solution is to use the [Wildcard type](https://www.elastic.co/guide/en/elasticsearch/reference/8.13/keyword.html#wildcard-field-type) which might be easier actually.

---

<div class="post-metadata">

**Author:** ![Umang\_Kamdar](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/umang_kamdar/32/135201_2.png) [@Umang\_Kamdar](https://discuss.elastic.co/u/Umang_Kamdar)\
**Post date:** [June 11, 2024, 6:44pm UTC](https://discuss.elastic.co/t/elasticsearch-query-for-exact-substring-matching-with-spaces/361216/5 "2024-06-11T18:44:49Z")

</div>

Seems like wildcard fields is not yet supported in the latest version of Opensearch as of now. Thought that opensearch should have the same types as of elasticsearch but it doesn't seem so yet.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [June 11, 2024, 6:44pm UTC](https://discuss.elastic.co/t/elasticsearch-query-for-exact-substring-matching-with-spaces/361216/6 "2024-06-11T18:44:49Z")

</div>

OpenSearch/OpenDistro are AWS run products and differ from the original Elasticsearch and Kibana products that Elastic builds and maintains. You may need to contact them directly for further assistance. See [What is OpenSearch and the OpenSearch Dashboard? | Elastic](https://www.elastic.co/elasticsearch/opensearch) for more details.

(This is an automated response from your friendly Elastic bot. Please report this post if you have any suggestions or concerns :elasticheart: )

---

<div class="post-metadata">

**Author:** ![dadoonet](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/dadoonet/32/137187_2.png) [@dadoonet](https://discuss.elastic.co/u/dadoonet)\
**Post date:** [June 11, 2024, 8:34pm UTC](https://discuss.elastic.co/t/elasticsearch-query-for-exact-substring-matching-with-spaces/361216/7 "2024-06-11T20:34:33Z")

</div>

Oh? You are using an outdated fork?

You should switch to Elasticsearch 8.14.0.  
It's complete, mature and secured.

And still free as it was before the fork, with even more features in the free tier.

---

<div class="post-metadata">

**Author:** ![Umang\_Kamdar](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/umang_kamdar/32/135201_2.png) [@Umang\_Kamdar](https://discuss.elastic.co/u/Umang_Kamdar)\
**Post date:** [June 12, 2024, 8:55am UTC](https://discuss.elastic.co/t/elasticsearch-query-for-exact-substring-matching-with-spaces/361216/8 "2024-06-12T08:55:42Z")

</div>

@dadoonet I am trying to use ngram tokenizer as you mentioned withe following settigns:

```auto
"settings": {
    "index": {
      "max_ngram_diff": 14
    },
    "analysis": {
      "tokenizer": {
        "my_ngram_tokenizer": {
          "type": "ngram",
          "min_gram": 1,
          "max_gram": 15,
          "token_chars": [
            "letter"
          ]
        }
      },
      "analyzer": {
        "my_ngram_analyzer": {
          "type": "custom",
          "tokenizer": "my_ngram_tokenizer",
          "filter": [
            "lowercase"
          ]
        }
      }
    }
  },

```

Now what's the best way to look for my exat substring? Is it like

```auto
GET index-new/_search
{
  "track_total_hits": true, 
  "query": {
   "match_phrase": {
     "description": "own f"
   }
  }
}

```

Or do you suggest any better way?

---

<div class="post-metadata">

**Author:** ![Christian\_Dahlqvist](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/christian_dahlqvist/32/4617_2.png) [@Christian\_Dahlqvist](https://discuss.elastic.co/u/Christian_Dahlqvist)\
**Post date:** [June 12, 2024, 9:09am UTC](https://discuss.elastic.co/t/elasticsearch-query-for-exact-substring-matching-with-spaces/361216/9 "2024-06-12T09:09:07Z")

</div>

As far as I can see, this is exactly the use case the wildcard field type was designed for. It uses ngrams behind the scenes to reduce the number of candidates it need to check and then matches the full pattern.

To get the same effect using standard ngrams you will need to rewrite the query and then perform post-processing on the results to filter out false positives. This can be tricky, so I would recommend upgrading to the latest version of Elasticsearch instead.
