# How to search for text within text?

**URL:** <https://discuss.elastic.co/t/how-to-search-for-text-within-text/366576>\
**Category:** Elasticsearch\
**Created:** [September 14, 2024, 4:31pm UTC](https://discuss.elastic.co/t/how-to-search-for-text-within-text/366576 "2024-09-14T16:31:50Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![dsagent](https://avatars.discourse-cdn.com/v4/letter/d/d2c977/32.png) [@dsagent](https://discuss.elastic.co/u/dsagent)\
**Post date:** [September 14, 2024, 4:31pm UTC](https://discuss.elastic.co/t/how-to-search-for-text-within-text/366576/1 "2024-09-14T16:31:50Z")

</div>

Hi

I have an index in which there is data, including the email, and I want to search in this field (email) for specific data, for example

[mary.smith@sakilacustomer.org](mailto:mary.smith@sakilacustomer.org)

I want to look for fields that contain smith from the middle of the email and .org or .com from the end of the email  
What is the most suitable for this so that the query is very fast

---

<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:** [September 14, 2024, 5:29pm UTC](https://discuss.elastic.co/t/how-to-search-for-text-within-text/366576/2 "2024-09-14T17:29:44Z")

</div>

Try this:

```auto
DELETE /test
PUT /test
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "my_tokenizer"
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "simple_pattern_split",
          "pattern": "[.@]"
        }
      }
    }
  },
  "mappings": {
    "properties": {
        "email": {
            "type": "text",
            "analyzer": "my_analyzer"
        }
    }
  }
}
POST /test/_doc
{
    "email": "mary.smith@sakilacustomer.org"
}
GET /test/_search
{
    "query": {
        "match": {
          "email": "mary"
        }
    }
}
GET /test/_search
{
    "query": {
        "match": {
          "email": "sakilacustomer"
        }
    }
}

```

If you want to understand what is happening behind the scene, run this:

```auto
GET /test/_analyze
{
    "analyzer": "my_analyzer",
    "text": ["mary.smith@sakilacustomer.org"]
}

```

This gives:

```auto
{
  "tokens": [
    {
      "token": "mary",
      "start_offset": 0,
      "end_offset": 4,
      "type": "word",
      "position": 0
    },
    {
      "token": "smith",
      "start_offset": 5,
      "end_offset": 10,
      "type": "word",
      "position": 1
    },
    {
      "token": "sakilacustomer",
      "start_offset": 11,
      "end_offset": 25,
      "type": "word",
      "position": 2
    },
    {
      "token": "org",
      "start_offset": 26,
      "end_offset": 29,
      "type": "word",
      "position": 3
    }
  ]
}

```

---

<div class="post-metadata">

**Author:** ![dsagent](https://avatars.discourse-cdn.com/v4/letter/d/d2c977/32.png) [@dsagent](https://discuss.elastic.co/u/dsagent)\
**Post date:** [September 14, 2024, 5:39pm UTC](https://discuss.elastic.co/t/how-to-search-for-text-within-text/366576/3 "2024-09-14T17:39:08Z")

</div>

> [@dadoonet](#):
>
> `smith`

I want the query to return all the emails according to the condition in the query  
For example  
GET index/\_search  
{  
"query": {  
"bool": {  
"must": [  
{  
"wildcard": {  
"email": {  
"value": "_smith_"  
}  
}  
},  
{  
"wildcard": {  
"email": {  
"value": "\*org"  
}  
}  
}  
]  
}  
}  
}

I want this query to return all the emails that contain in the middle of it the Im smith and at the end of it .org

---

<div class="post-metadata">

**Author:** ![dsagent](https://avatars.discourse-cdn.com/v4/letter/d/d2c977/32.png) [@dsagent](https://discuss.elastic.co/u/dsagent)\
**Post date:** [September 14, 2024, 5:45pm UTC](https://discuss.elastic.co/t/how-to-search-for-text-within-text/366576/4 "2024-09-14T17:45:20Z")

</div>

This is Saud all the identical values whether they are in the middle or the beginning or the end and I do not want this I want the value that I specify in the query exactly  
For example I want the one in the middle and I don't want any other similar values to query from the values at the end or the beginning I just want the one in the middle

---

<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:** [September 14, 2024, 9:38pm UTC](https://discuss.elastic.co/t/how-to-search-for-text-within-text/366576/5 "2024-09-14T21:38:23Z")

</div>

Please reproduce the problem, the same way I did. That will help to understand exactly what you have and what you want.

---

<div class="post-metadata">

**Author:** ![dsagent](https://avatars.discourse-cdn.com/v4/letter/d/d2c977/32.png) [@dsagent](https://discuss.elastic.co/u/dsagent)\
**Post date:** [September 16, 2024, 5:51am UTC](https://discuss.elastic.co/t/how-to-search-for-text-within-text/366576/6 "2024-09-16T05:51:31Z")

</div>

> [@dadoonet](#):
>
> Please reproduce the problem, the same way I did. That will help to understand exactly what you have and what you want.

The query has no problem but it is very slow

---

<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:** [September 16, 2024, 6:30am UTC](https://discuss.elastic.co/t/how-to-search-for-text-within-text/366576/7 "2024-09-16T06:30:48Z")

</div>

There are 2 possibilities from here:

- you continue to use wildcards and the query will remain slow
- you change the query / mapping to find a faster way to get your results

I proposed something which is must faster but you answered this is not answering your use case.  
So I asked, please reproduce your use case so we can help you.  
You answered that you don't have any problem with the query but it just slow.

Not sure how to help if you don't want to be helped.

---

<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:** [September 16, 2024, 6:39am UTC](https://discuss.elastic.co/t/how-to-search-for-text-within-text/366576/8 "2024-09-16T06:39:03Z")

</div>

Create the mapping David presented above and index the document he used as an example. You should then be able to query it as follows without requiring any wildcard queries, which should speed it up considerably.

```auto
GET test/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "email": "smith"
          }
        },
        {
          "match": {
            "email": "org"
          }
        }
      ]
    }
  }
}

```

As the field is tokenised you can query directly on the individual components, which you can see from the analysis output above.

---

<div class="post-metadata">

**Author:** ![dsagent](https://avatars.discourse-cdn.com/v4/letter/d/d2c977/32.png) [@dsagent](https://discuss.elastic.co/u/dsagent)\
**Post date:** [September 16, 2024, 6:48am UTC](https://discuss.elastic.co/t/how-to-search-for-text-within-text/366576/9 "2024-09-16T06:48:40Z")

</div>

> [@dadoonet](#):
>
> Not sure how to help if you don't want to be helped.

I am sorry  
I really want to help because he became very slow and tired

What do you want me to do because when I understand what exactly you mean

---

<div class="post-metadata">

**Author:** ![dsagent](https://avatars.discourse-cdn.com/v4/letter/d/d2c977/32.png) [@dsagent](https://discuss.elastic.co/u/dsagent)\
**Post date:** [September 16, 2024, 6:52am UTC](https://discuss.elastic.co/t/how-to-search-for-text-within-text/366576/10 "2024-09-16T06:52:35Z")

</div>

Yes, your words are correct, but this returns any similar data and the use case does not allow that, so it is necessary to return the exact similar data

---

<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:** [September 16, 2024, 6:54am UTC](https://discuss.elastic.co/t/how-to-search-for-text-within-text/366576/11 "2024-09-16T06:54:54Z")

</div>

> [@dsagent](#):
>
> Yes, your words are correct, but this returns any similar data and the use case does not allow that, so it is necessary to return the exact similar data

I do not understand what you mean by that. You need to provide explicit examples of what does and what does not work.

Please show an example with a query and sample data and what is returned that you do not want and a sample document that is not returned even though you expect it to be.

If you want to search on specific parts of the string and not treat it all as a list of tokens you can break out components into separate fields, e.g. like this:

```auto
POST /test/_doc
{
    "email": "mary.smith@sakilacustomer.org",
    "domain": "sakilacustomer.org",
    "domain_suffix": "org"
}

```

Here you can search on the whole email address but also on the domain or just the suffix without using wildcards, which should be fast and scale well.

If you do not want to break out parts into separate fields in the source document you may also be able to achieve this through multi fields using different analysers.

---

<div class="post-metadata">

**Author:** ![dsagent](https://avatars.discourse-cdn.com/v4/letter/d/d2c977/32.png) [@dsagent](https://discuss.elastic.co/u/dsagent)\
**Post date:** [September 16, 2024, 7:06am UTC](https://discuss.elastic.co/t/how-to-search-for-text-within-text/366576/12 "2024-09-16T07:06:09Z")

</div>

{

"mappings": {

```
"properties": {
  "active": {
    "type": "long"
  },
  "activebool": {
    "type": "boolean"
  },
  "address_id": {
    "type": "long"
  },
  "create_date": {
    "type": "date"
  },
  "customer_id": {
    "type": "long"
  },
  "email": {
    "type": "text",
    
    "fields": {
      "keyword": {
        "type": "keyword",
        "ignore_above": 256
      }
    }
  },
  "first_name": {
    "type": "text",
    "fields": {
      "keyword": {
        "type": "keyword",
        "ignore_above": 256
      }
    }
  },
  "last_name": {
    "type": "text",
    "fields": {
      "keyword": {
        "type": "keyword",
        "ignore_above": 256
      }
    }
  },
  "last_update": {
    "type": "text",
    "fields": {
      "keyword": {
        "type": "keyword",
        "ignore_above": 256
      }
    }
  },
  "store_id": {
    "type": "long"
  }
}

```

}

}

These are my mappings

---

<div class="post-metadata">

**Author:** ![dsagent](https://avatars.discourse-cdn.com/v4/letter/d/d2c977/32.png) [@dsagent](https://discuss.elastic.co/u/dsagent)\
**Post date:** [September 16, 2024, 7:09am UTC](https://discuss.elastic.co/t/how-to-search-for-text-within-text/366576/13 "2024-09-16T07:09:52Z")

</div>

POST /uep/\_search  
{  
"query": {  
"bool": {  
"must": [  
{  
"wildcard": {  
"email": "_smith_"  
}  
},  
{  
"wildcard": {  
"email": "\*.org"  
}  
}  
]  
}  
}  
}

This is my query that returns the data very accurately and that I want the data to be exactly the same as the data it returns

---

<div class="post-metadata">

**Author:** ![dsagent](https://avatars.discourse-cdn.com/v4/letter/d/d2c977/32.png) [@dsagent](https://discuss.elastic.co/u/dsagent)\
**Post date:** [September 16, 2024, 7:11am UTC](https://discuss.elastic.co/t/how-to-search-for-text-within-text/366576/14 "2024-09-16T07:11:08Z")

</div>

{  
"took": 5,  
"timed\_out": false,  
"\_shards": {  
"total": 1,  
"successful": 1,  
"skipped": 0,  
"failed": 0  
},  
"hits": {  
"total": {  
"value": 2,  
"relation": "eq"  
},  
"max\_score": 2,  
"hits": [  
{  
"\_index": "uep",  
"\_id": "ha0j8ZEBH-KoI\_5wv58R",  
"\_score": 2,  
"\_source": {  
"customer\_id": 1,  
"store\_id": 1,  
"first\_name": "Mary",  
"last\_name": "Smith",  
"email": "[mary.smith@sakilacustomer.org](mailto:mary.smith@sakilacustomer.org)",  
"address\_id": 5,  
"activebool": true,  
"create\_date": "2006-02-14",  
"last\_update": "2013-05-26 14:49:45.738",  
"active": 1  
}  
},  
{  
"\_index": "uep",  
"\_id": "bq0j8ZEBH-KoI\_5wy6Iv",  
"\_score": 2,  
"\_source": {  
"customer\_id": 1,  
"store\_id": 1,  
"first\_name": "Mary",  
"last\_name": "Smith",  
"email": "[mary.smith@sakilacustomer.org](mailto:mary.smith@sakilacustomer.org)",  
"address\_id": 5,  
"activebool": true,  
"create\_date": "2006-02-14",  
"last\_update": "2013-05-26 14:49:45.738",  
"active": 1  
}  
}  
]  
}  
}

These results are returned by the query

---

<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:** [September 16, 2024, 7:12am UTC](https://discuss.elastic.co/t/how-to-search-for-text-within-text/366576/15 "2024-09-16T07:12:50Z")

</div>

In order to achieve what you want I believe you will need to change your mappings and get away from the slow wildcard queries. I would recommend setting up a small test index with the mappings David suggested and load this with a small subset of your data. You can then test and iterate on mappings and queries until you find something that works for you.

---

<div class="post-metadata">

**Author:** ![dsagent](https://avatars.discourse-cdn.com/v4/letter/d/d2c977/32.png) [@dsagent](https://discuss.elastic.co/u/dsagent)\
**Post date:** [September 16, 2024, 7:13am UTC](https://discuss.elastic.co/t/how-to-search-for-text-within-text/366576/16 "2024-09-16T07:13:39Z")

</div>

Conclusion  
I want a way to do this and repeat the exact same data shown above

---

<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:** [September 16, 2024, 7:14am UTC](https://discuss.elastic.co/t/how-to-search-for-text-within-text/366576/17 "2024-09-16T07:14:41Z")

</div>

> [@dsagent](#):
>
> Conclusion  
> I want a way to do this and repeat the exact same data shown above

We have told you what to do but you do not seem to listen. I do not have time for this type of pointless back-and-fourth without any progress so wish you good luck.

If you insist on using wildcard queries, changing your mappings to include the [wildcard field type](https://www.elastic.co/guide/en/elasticsearch/reference/current/keyword.html#wildcard-field-type) would make this faster, even though it likely will be slower than the other approaches described.

---

<div class="post-metadata">

**Author:** ![dsagent](https://avatars.discourse-cdn.com/v4/letter/d/d2c977/32.png) [@dsagent](https://discuss.elastic.co/u/dsagent)\
**Post date:** [September 16, 2024, 7:37am UTC](https://discuss.elastic.co/t/how-to-search-for-text-within-text/366576/18 "2024-09-16T07:37:28Z")

</div>

> [@Christian\_Dahlqvist](#):
>
> We have told you what to do but you do not seem to listen. I do not have time for this type of pointless back-and-fourth without any progress so wish you good luck.

Sorry about that.  
I have done everything you suggested and I highly appreciate your efforts with me

Look, that's what I suggested, friend.  
PUT /test  
{  
"settings": {  
"analysis": {  
"analyzer": {  
"my\_analyzer": {  
"tokenizer": "my\_tokenizer"  
}  
},  
"tokenizer": {  
"my\_tokenizer": {  
"type": "simple\_pattern\_split",  
"pattern": "[.@]"  
}  
}  
}  
},  
"mappings": {  
"properties": {  
"email": {  
"type": "text",  
"analyzer": "my\_analyzer"  
}  
}  
}  
}

POST /test/\_doc  
{  
"email": "[mary.ssmith@sakilacustomergg.org](mailto:mary.ssmith@sakilacustomergg.org)"  
}

And I made a query like this

GET /test/\_search  
{  
"query": {  
"match": {  
"email": "\*org"  
}  
}  
}

And these are the outputs  
{  
"took": 0,  
"timed\_out": false,  
"\_shards": {  
"total": 1,  
"successful": 1,  
"skipped": 0,  
"failed": 0  
},  
"hits": {  
"total": {  
"value": 0,  
"relation": "eq"  
},  
"max\_score": null,  
"hits":   
}  
}

Note that it does not return anything and if you delete \* it will return the values when you can stand the word anywhere in the email and I do not want it to do that I want the word to be at the end of the email only if not at the end of the email do not repeat it

---

<div class="post-metadata">

**Author:** ![dsagent](https://avatars.discourse-cdn.com/v4/letter/d/d2c977/32.png) [@dsagent](https://discuss.elastic.co/u/dsagent)\
**Post date:** [September 16, 2024, 7:39am UTC](https://discuss.elastic.co/t/how-to-search-for-text-within-text/366576/19 "2024-09-16T07:39:41Z")

</div>

> [@Christian\_Dahlqvist](#):
>
> If you insist on using wildcard queries, changing your mappings to include the [wildcard field type](https://www.elastic.co/guide/en/elasticsearch/reference/current/keyword.html#wildcard-field-type) would make this faster, even though it likely will be slower than the other approaches described.

I think if I'm going to use it, there's no way out of it.
