# What is the best way to query first and last name?

**URL:** https://discuss.elastic.co/t/what-is-the-best-way-to-query-first-and-last-name/136142
**Category:** Elasticsearch
**Created:** [June 15, 2018, 9:17pm UTC](https://discuss.elastic.co/t/what-is-the-best-way-to-query-first-and-last-name/136142 "2018-06-15T21:17:57Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![undefinedman](https://avatars.discourse-cdn.com/v4/letter/u/6bbea6/32.png) [@undefinedman](https://discuss.elastic.co/u/undefinedman)
#### Post date: [June 15, 2018, 9:17pm UTC](https://discuss.elastic.co/t/what-is-the-best-way-to-query-first-and-last-name/136142/1 "2018-06-15T21:17:58Z")

</div>

I am trying to setup search analysis in Elasticsearch to get as close as possible to the following scenario:

I have **4** users:

1. Karolina Abc ([karolinaabc@example.com](mailto:karolinaabc@example.com))
2. Karolina Def ([karolinadef@example.com](mailto:karolinadef@example.com))
3. Karol Abc ([karolabc@example.com](mailto:karolabc@example.com))
4. Karol Adf ([karoladf@example.com](mailto:karoladf@example.com))

* * *

When I type:  
_"Kar"_

I should get **all 4 users**.

* * *

When I type:  
_"Karol"_

I still should get **all 4 users**.

* * *

When I type:  
_"Karol A"_

I should get **user no. 3 & 4**.

* * *

When I type:  
_"Karol Ad"_

I should get **user no. 4 only**.

So when I start typing it should start matching let's say first 3 chars for field **firstName** , **lastName** and **emailAddress** and for that I use **MultiMatch**. The result should narrow once I type more chars and in the end return only ones that matches my query string.

The problem is that when I type now _"Karol Ad"_ it returns all 4 users because _"Karol"_ matches _"Karolina"_.

I have the following setup:

```
        settings:
            index:
                analysis:
                    analyzer:
                        search_analyzer:
                            type: custom
                            tokenizer: standard
                            filter: [lowercase, edge_ngram]
                    filter:
                        edge_ngram:
                            type: edge_ngram
                            min_gram: 1
                            max_gram: 10

```

and

```
    $boolQuery = new Query\BoolQuery();

    $boolQuery->addMust((new Query\MultiMatch())
        ->setFields(['firstName', 'lastName', 'emailAddress'])
        ->setType(Query\MultiMatch::TYPE_CROSS_FIELDS)
        ->setQuery('Karol Ad')
        ->setOperator('and')
    );

    $query = new Query();
    $query->setQuery($boolQuery);

    $result = $this->finder->find($query);

```

Is there anyone that may know the solution to the problem I am facing?

---

<div class="post-metadata">

### Author: ![klof](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/klof/32/31590_2.png) [@klof](https://discuss.elastic.co/u/klof)
#### Post date: [June 16, 2018, 6:15am UTC](https://discuss.elastic.co/t/what-is-the-best-way-to-query-first-and-last-name/136142/2 "2018-06-16T06:15:27Z")

</div>

Can we see the mapping of the fields as well pls?  
Because your approach looks fine...  
Can you confirm that you have a `"search_analyzer": "standard"` in your fields mapping?

[https://www.elastic.co/guide/en/elasticsearch/reference/6.2/search-analyzer.html#search-analyzer](https://www.elastic.co/guide/en/elasticsearch/reference/6.2/search-analyzer.html#search-analyzer)

---

<div class="post-metadata">

### Author: ![undefinedman](https://avatars.discourse-cdn.com/v4/letter/u/6bbea6/32.png) [@undefinedman](https://discuss.elastic.co/u/undefinedman)
#### Post date: [June 16, 2018, 12:56pm UTC](https://discuss.elastic.co/t/what-is-the-best-way-to-query-first-and-last-name/136142/3 "2018-06-16T12:56:54Z")

</div>

Hey klof, thank you for your answer.

I think I found the solution. In my example above I use `edge_ngram` which is causing that _"Karol"_ is found in _"Karolina"_ word. I have changed my approach a bit.

Let's take a look at this:

```
         settings:
            index:
                analysis:
                    analyzer:
                        search_analyzer:
                            type: custom
                            tokenizer: keyword
                            filter: [lowercase]

```

As you can see, I got rid of `edge_ngram` filter and i removed `standard` tokenizer and implemented `keyword` tokenizer instead.

Surely I have mapped `search_analyzer` to my fields.

Now, PHP part:

```
    $boolQuery->addMust((new Query\MultiMatch())
        ->setFields(['fullName', 'lastName', 'emailAddress'])
        ->setType(Query\MultiMatch::TYPE_PHRASE_PREFIX)
        ->setQuery($this->query)
    );

```

I got rid of `TYPE_CROSS_FIELDS` and added `TYPE_PHRASE_PREFIX` instead.

And finally it works the way I want. So when I type _"Karol A"_ I don't get other results anymore.

There is a minor issue only. When subject has two words, e.g. _"Hello world"_ it will not match when I type _"word"_.

---

<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: [July 14, 2018, 12:56pm UTC](https://discuss.elastic.co/t/what-is-the-best-way-to-query-first-and-last-name/136142/4 "2018-07-14T12:56:59Z")

</div>

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