# Term matching with elastic search edge n gram

**URL:** <https://discuss.elastic.co/t/term-matching-with-elastic-search-edge-n-gram/73891>\
**Category:** Elasticsearch\
**Created:** [February 3, 2017, 5:23pm UTC](https://discuss.elastic.co/t/term-matching-with-elastic-search-edge-n-gram/73891 "2017-02-03T17:23:35Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![venkata\_sreekanth\_bh](https://avatars.discourse-cdn.com/v4/letter/v/65b543/32.png) [@venkata\_sreekanth\_bh](https://discuss.elastic.co/u/venkata_sreekanth_bh)\
**Post date:** [February 3, 2017, 5:23pm UTC](https://discuss.elastic.co/t/term-matching-with-elastic-search-edge-n-gram/73891/1 "2017-02-03T17:23:35Z")

</div>

I have an custom analyzer with char replace filter, keyword tokenizer and lowercase filter. The problem I want solve is follows

Original string in index : 1812abcdefg

user input query : 812abcdefg

the index has other strings such as 812c, 812ab etc.

I want to be able to allow one or two characters preceding the edge ngram. I have tried ngram but the strings can of varying length from 1 to 50 characters and it throws off search.

Does anybody have any idea to do this?

---

<div class="post-metadata">

**Author:** ![polyfractal](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/polyfractal/32/48162_2.png) [@polyfractal](https://discuss.elastic.co/u/polyfractal)\
**Post date:** [February 3, 2017, 6:45pm UTC](https://discuss.elastic.co/t/term-matching-with-elastic-search-edge-n-gram/73891/2 "2017-02-03T18:45:52Z")

</div>

So you essentially need a suffix search? E.g. `*812abcdefg`?

The best way to do that is add another analysis chain, which includes a reverse filter. Then use a prefix query.

So the reverse filter will index `1812abcdefg` as `gfedcba2181`. When you use a prefix query on that same analysis chain, `812abcdefg` will be converted into `gfedcba218*` and you'll get your match without an expensive suffix wildcard.

---

<div class="post-metadata">

**Author:** ![venkata\_sreekanth\_bh](https://avatars.discourse-cdn.com/v4/letter/v/65b543/32.png) [@venkata\_sreekanth\_bh](https://discuss.elastic.co/u/venkata_sreekanth_bh)\
**Post date:** [February 3, 2017, 9:27pm UTC](https://discuss.elastic.co/t/term-matching-with-elastic-search-edge-n-gram/73891/3 "2017-02-03T21:27:45Z")

</div>

> [@polyfractal](#):
>
> suffix wildcard.

I will try that and get back to you

---

<div class="post-metadata">

**Author:** ![venkata\_sreekanth\_bh](https://avatars.discourse-cdn.com/v4/letter/v/65b543/32.png) [@venkata\_sreekanth\_bh](https://discuss.elastic.co/u/venkata_sreekanth_bh)\
**Post date:** [February 3, 2017, 9:47pm UTC](https://discuss.elastic.co/t/term-matching-with-elastic-search-edge-n-gram/73891/4 "2017-02-03T21:47:09Z")

</div>

> [@polyfractal](#):
>
> gfedcba218

Is there a way to perform sub-string search, while the above mentioned reverse filter is definitely a good idea some times the original string in the index can be like

1812abcdefg-pby-reel, 1812abcdefg123 etc. in this scenario the reverse filter may not work. I do use char replace filter to remove non word characters.

---

<div class="post-metadata">

**Author:** ![polyfractal](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/polyfractal/32/48162_2.png) [@polyfractal](https://discuss.elastic.co/u/polyfractal)\
**Post date:** [February 3, 2017, 10:26pm UTC](https://discuss.elastic.co/t/term-matching-with-elastic-search-edge-n-gram/73891/5 "2017-02-03T22:26:04Z")

</div>

You can also use ngrams / shingles with the reverse approach. So then you'll be indexing reversed fragments, which will match the prefix query. Basically the exact same analyzer you have now, except add a reverse filter to it.

Also, most people who implement this strategy also index the forward direction too, so that they get both prefix and suffix search.

---

<div class="post-metadata">

**Author:** ![venkata\_sreekanth\_bh](https://avatars.discourse-cdn.com/v4/letter/v/65b543/32.png) [@venkata\_sreekanth\_bh](https://discuss.elastic.co/u/venkata_sreekanth_bh)\
**Post date:** [February 4, 2017, 12:02am UTC](https://discuss.elastic.co/t/term-matching-with-elastic-search-edge-n-gram/73891/6 "2017-02-04T00:02:53Z")

</div>

ngrams is reverse is likely to score other tokens higher. Shingles is not an option since there are no stop words. The terms are like part numbers and have no stop words.

I hope there is some way to search sub strings without using regex or wildcard. Also, I am not able to embed regex or wildcard in bool query in the sense that it has not effect.

---

<div class="post-metadata">

**Author:** ![forloop](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/forloop/32/9021_2.png) [@forloop](https://discuss.elastic.co/u/forloop)\
**Post date:** [February 6, 2017, 5:26am UTC](https://discuss.elastic.co/t/term-matching-with-elastic-search-edge-n-gram/73891/7 "2017-02-06T05:26:41Z")

</div>

> [@venkata\_sreekanth\_bh](#):
>
> Shingles is not an option since there are no stop words

You don't need stop words to [use shingles](https://www.elastic.co/blog/searching-with-shingles)

---

<div class="post-metadata">

**Author:** ![venkata\_sreekanth\_bh](https://avatars.discourse-cdn.com/v4/letter/v/65b543/32.png) [@venkata\_sreekanth\_bh](https://discuss.elastic.co/u/venkata_sreekanth_bh)\
**Post date:** [February 7, 2017, 6:47pm UTC](https://discuss.elastic.co/t/term-matching-with-elastic-search-edge-n-gram/73891/9 "2017-02-07T18:47:12Z")

</div>

I am using ngram with diff min and max gram values to do substring search

---

<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:** [March 7, 2017, 6:47pm UTC](https://discuss.elastic.co/t/term-matching-with-elastic-search-edge-n-gram/73891/10 "2017-03-07T18:47:24Z")

</div>

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