# Case insensitive regex query with character range

**URL:** <https://discuss.elastic.co/t/case-insensitive-regex-query-with-character-range/376136>\
**Category:** Elasticsearch\
**Created:** [March 19, 2025, 5:08pm UTC](https://discuss.elastic.co/t/case-insensitive-regex-query-with-character-range/376136 "2025-03-19T17:08:14Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![petrsimon](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/petrsimon/32/142139_2.png) [@petrsimon](https://discuss.elastic.co/u/petrsimon)\
**Post date:** [March 19, 2025, 5:08pm UTC](https://discuss.elastic.co/t/case-insensitive-regex-query-with-character-range/376136/1 "2025-03-19T17:08:14Z")

</div>

Hi,  
I'm implementing regex search on ES 8.16 (using java client) against fields of type `keyword` and I came across strange issue when sending the `case_insensitive: true` option.

1. "[abc]+" -\> "abc", "ABC"
2. "[ABC]+" -\> "abc", "ABC"
3. "[a-c]+" -\> "abc"
4. "[A-C]+" -\> "ABC"

Is there an explanation for this or is it a bug in lucene or ES?

Thanks a lot for any insight!

---

<div class="post-metadata">

**Author:** ![Mark\_Harwood1](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/mark_harwood1/32/101255_2.png) [@Mark\_Harwood1](https://discuss.elastic.co/u/Mark_Harwood1)\
**Post date:** [March 19, 2025, 11:14pm UTC](https://discuss.elastic.co/t/case-insensitive-regex-query-with-character-range/376136/2 "2025-03-19T23:14:10Z")

</div>

My guess is that the case sensitivity only applies to explicitly listed characters and because steps 3 and 4 have some unstated characters (b and B respectively) these are not interpreted as you'd hope.  
This is arguably a bug in Lucene.

---

<div class="post-metadata">

**Author:** ![petrsimon](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/petrsimon/32/142139_2.png) [@petrsimon](https://discuss.elastic.co/u/petrsimon)\
**Post date:** [March 20, 2025, 9:03am UTC](https://discuss.elastic.co/t/case-insensitive-regex-query-with-character-range/376136/3 "2025-03-20T09:03:07Z")

</div>

I've tried reproducing in lucene 10, but there it only returns exactly what's in the the regex, i.e. regarless of the ASCII\_CASE\_INSENSITIVE flag. So apparently the

1. "[abc]+" -\> "abc", "ABC"
2. "[ABC]+" -\> "abc", "ABC"

is implemented in ES.

---

<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:** [March 20, 2025, 9:11am UTC](https://discuss.elastic.co/t/case-insensitive-regex-query-with-character-range/376136/4 "2025-03-20T09:11:24Z")

</div>

> [@petrsimon](#):
>
> - "[a-c]+" -\> "abc"
> - "[A-C]+" -\> "ABC"

I believe the issue is that ranges where all characters are not explicitly stated are not working. Did you test the ones quoted above?

---

<div class="post-metadata">

**Author:** ![petrsimon](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/petrsimon/32/142139_2.png) [@petrsimon](https://discuss.elastic.co/u/petrsimon)\
**Post date:** [March 20, 2025, 9:25am UTC](https://discuss.elastic.co/t/case-insensitive-regex-query-with-character-range/376136/5 "2025-03-20T09:25:04Z")

</div>

Yes, I've tested all these patterns, in Lucene with KeywordAnalyzer it's doing

1. "[abc]+" -\> "abc"
2. "[ABC]+" -\> "ABC"
3. "[a-c]+" -\> "abc"
4. "[A-C]+" -\> "ABC"

---

<div class="post-metadata">

**Author:** ![petrsimon](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/petrsimon/32/142139_2.png) [@petrsimon](https://discuss.elastic.co/u/petrsimon)\
**Post date:** [March 20, 2025, 9:38am UTC](https://discuss.elastic.co/t/case-insensitive-regex-query-with-character-range/376136/6 "2025-03-20T09:38:40Z")

</div>

Lucene test [GitHub - petrsimon/lucene-regex](https://github.com/petrsimon/lucene-regex)

---

<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:** [March 20, 2025, 10:15am UTC](https://discuss.elastic.co/t/case-insensitive-regex-query-with-character-range/376136/7 "2025-03-20T10:15:24Z")

</div>

> [@Mark\_Harwood1](#):
>
> This is arguably a bug in Lucene.

I agree and at least this should be documented I think.

---

<div class="post-metadata">

**Author:** ![petrsimon](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/petrsimon/32/142139_2.png) [@petrsimon](https://discuss.elastic.co/u/petrsimon)\
**Post date:** [March 20, 2025, 12:33pm UTC](https://discuss.elastic.co/t/case-insensitive-regex-query-with-character-range/376136/8 "2025-03-20T12:33:10Z")

</div>

I've reported it at [Case insensitive regex query with character range · Issue #14378 · apache/lucene · GitHub](https://github.com/apache/lucene/issues/14378). Thanks all for your feedback.

---

<div class="post-metadata">

**Author:** ![petrsimon](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/petrsimon/32/142139_2.png) [@petrsimon](https://discuss.elastic.co/u/petrsimon)\
**Post date:** [March 20, 2025, 3:42pm UTC](https://discuss.elastic.co/t/case-insensitive-regex-query-with-character-range/376136/9 "2025-03-20T15:42:33Z")

</div>

Seems like it's a known limitation of Lucene. Perhaps it would be nice to document it also in ES?

---

<div class="post-metadata">

**Author:** ![RainTown](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/raintown/32/140206_2.png) [@RainTown](https://discuss.elastic.co/u/RainTown)\
**Post date:** [March 20, 2025, 4:47pm UTC](https://discuss.elastic.co/t/case-insensitive-regex-query-with-character-range/376136/10 "2025-03-20T16:47:54Z")

</div>

Good spot @petrsimon !!

This is sort of thing that would infuriate me if I found that the regex `[abc]+` isn't treated exactly the same as `[a-c]+`. Really subtle and certainly counter-intuitive and therefore difficult to catch via testing in real world, creating really subtle user issues.

I note that at

> **[RegExp (Lucene 10.1.0 core API)](https://lucene.apache.org/core/10_1_0/core/org/apache/lucene/util/automaton/RegExp.html)**
>
> declaration: package: org.apache.lucene.util.automaton, class: RegExp

it does not really give any detail on the scope of Lucene regex support - POSIX BRE / POSIX ERE / PCRE / ... It's clearly some subset, maybe documented elsewhere? Sadly the ES documentation at:

> **[Regular expression syntax | Elasticsearch Guide \[8.17\] | Elastic](https://www.elastic.co/guide/en/elasticsearch/reference/current/regexp-syntax.html)**

has exactly the (unfortunate) example above -

> `[…]`
> 
> Match one of the characters in the brackets. For example:
> 
> [abc] # matches 'a', 'b', 'c'
> 
> Inside the brackets, `-` indicates a range unless `-` is the first character or escaped. For example:
> 
> [a-c] # matches 'a', 'b', or 'c'

The strong implication is that those 2 things are functionally equivalent. But they are clearly not 100% equivalent.

I can see the argument around character classes supporting different languages, where upper/lower case is more complex, so it's all more complicated than at first glance, .... But still it's hard to square that with `[abc]` meaning one thing `[a-c]` meaning another.

Suggestion to try to add some note to the ES doc above, I note it already documents the lack of anchors. Maybe also on pages where the case\_insensitive: true/false toggle is documented.

---

<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:** [March 21, 2025, 3:07pm UTC](https://discuss.elastic.co/t/case-insensitive-regex-query-with-character-range/376136/11 "2025-03-21T15:07:26Z")

</div>

Thanks all for reporting this and helping on this topic.

@Liam_Thompson created this PR to add some clarification in our documentation.

> <https://github.com/elastic/elasticsearch/pull/125412>
>
> Flagged by @dadoonet in Slack:
> 
> \> There's an interesting discussion \[on discu…ss\](https://discuss.elastic.co/t/case-insensitive-regex-query-with-character-range/376136/9?u=dadoonet) about \[Lucene regex\](https://lucene.apache.org/core/10\_1\_0/core/org/apache/lucene/util/automaton/RegExp.html) support.  
> \> Our \[documentation\](https://www.elastic.co/guide/en/elasticsearch/reference/current/regexp-syntax.html#regexp-standard-operators) says things like:  
> \> 
> \> - \`\[a-c\] # matches 'a', 'b', or 'c'\`
> \> - \`\[^a-c\] # matches any character except 'a', 'b', or 'c'\`
> \> 
> \> Which is correct unless you use as well \`case\_insensitive: true\` option. In which case you would expect \`B\` to match \`\[a-c\]\`. But it does not work that way and it's a known limitation as Robert answered in \[https://github.com/apache/lucene/issues/14378#issuecomment-2740658343\](https://github.com/apache/lucene/issues/14378#issuecomment-2740658343).  
> \>
