# Phrase Query with Prefix produces 0 results

**URL:** https://discuss.elastic.co/t/phrase-query-with-prefix-produces-0-results/172549
**Category:** Elasticsearch
**Created:** [March 15, 2019, 2:19pm UTC](https://discuss.elastic.co/t/phrase-query-with-prefix-produces-0-results/172549 "2019-03-15T14:19:57Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![myronuecker](https://avatars.discourse-cdn.com/v4/letter/m/35a633/32.png) [@myronuecker](https://discuss.elastic.co/u/myronuecker)
#### Post date: [March 15, 2019, 2:19pm UTC](https://discuss.elastic.co/t/phrase-query-with-prefix-produces-0-results/172549/1 "2019-03-15T14:19:57Z")

</div>

We are replacing a homegrown search engine written with pure Lucene (currently 4.9.1) with ElasticSearch. After adding the search analyzers we used in the old system, I'm now trying to replicate our queries. Right now I'm looking at replacing our "starts with" query with the same syntax in ElasticSearch. It appears that either query\_string or simple\_query\_string should support the original Lucene syntax, but that doesn't seem to be the case.

I have a field that is analyzed using whitespace tokenizer and both lowercase and asciifolding filters. I'm trying to run a query that has a phrase query with a prefix.

Specifically, we are trying to find documents with one or more names, but I expect it to work in other cases as well. For example, I want to be able to find all documents with a name starting with “Smith John”, such as “Smith John”, “Smith Johnny”, “Smith John A”, etc. If a document has “Smith Barry” and “Wilson John”, but doesn’t have a version of “Smith John”, I don’t want to find that document.

This query will find all documents that have exactly "smith john" in the field "name" but no other variations.

```
{
"query": {
    "simple_query_string": {
        "query": "\"smith john\"",
        "fields": ["name"],
        "default_operator": "AND"
        }
    }
}

```

If I remove the quotes and add a prefix operator, the query will find “Smith John”, “Smith John A”, “Smith Johnny”, but also find any documents with both “Smith Barry” and “Wilson John” because it searches across instances.

```
{
"query": {
    "simple_query_string": {
        "query": "smith john*",
        "fields": ["name"],
        "default_operator": "AND"
        }
    }
}

```

The next query is what I'm trying to use, and it does work in our old system with pure Lucene. The quotes tell it to search across only one instance, and the asterisk (_) tells it to do a prefix query. However, in ElasticSearch that same syntax never produces any results. I’m guessing it is actually looking for “john_” instead of treating the asterisk as a prefix operator.

```
{
"query": {
    "simple_query_string": {
        "query": "\"smith john*\"",
        "fields": ["name"],
        "default_operator": "AND"
        }
    }
}

```

I have tried variations of query\_string as well with similar results.

I have successfully done this using "match\_phrase\_prefix" to search for "smith john", but that comes with its own limitations such as not allowing wildcards and needing to know or guess at a value for max\_expansions. I found that if I use too small of a number I get partial results, and the documentation warns that too large of a number affects performance.

What do I need to change to get the results I want from this query? Thank you.

---

<div class="post-metadata">

### Author: ![myronuecker](https://avatars.discourse-cdn.com/v4/letter/m/35a633/32.png) [@myronuecker](https://discuss.elastic.co/u/myronuecker)
#### Post date: [March 15, 2019, 7:55pm UTC](https://discuss.elastic.co/t/phrase-query-with-prefix-produces-0-results/172549/2 "2019-03-15T19:55:34Z")

</div>

I did figure out that we do have a custom implementation of Query that is the reason this works for us now. However, I would be much happier if there was an out-of-the-box way to do it in ElasticSearch.

---

<div class="post-metadata">

### Author: ![safwan](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/safwan/32/31879_2.png) [@safwan](https://discuss.elastic.co/u/safwan)
#### Post date: [March 15, 2019, 8:40pm UTC](https://discuss.elastic.co/t/phrase-query-with-prefix-produces-0-results/172549/3 "2019-03-15T20:40:00Z")

</div>

It actually depends on your mapping and the analyzer you are using. Can you please share them as well?

---

<div class="post-metadata">

### Author: ![myronuecker](https://avatars.discourse-cdn.com/v4/letter/m/35a633/32.png) [@myronuecker](https://discuss.elastic.co/u/myronuecker)
#### Post date: [March 15, 2019, 8:46pm UTC](https://discuss.elastic.co/t/phrase-query-with-prefix-produces-0-results/172549/5 "2019-03-15T20:46:04Z")

</div>

The analyzer we have is:

```
{
	"MyAnalyzer": {
		"filter": [
			"lowercase",
			"asciifolding"
		],
		"type": "custom",
		"tokenizer": "whitespace"
	}
}

```

and the field mapping is:

```
{
	"text_field": {
		"type": "text",
		"fields": {
			"raw": {
				"type": "keyword"
			}
		},
		"analyzer": "MyAnalyzer"
	}
}
```

---

<div class="post-metadata">

### Author: ![safwan](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/safwan/32/31879_2.png) [@safwan](https://discuss.elastic.co/u/safwan)
#### Post date: [March 15, 2019, 8:54pm UTC](https://discuss.elastic.co/t/phrase-query-with-prefix-produces-0-results/172549/6 "2019-03-15T20:54:09Z")

</div>

> [@myronuecker](#):
>
> For example, I want to be able to find all documents with a name starting with “Smith John”, such as “Smith John”, “Smith Johnny”, “Smith John A”, etc. If a document has “Smith Barry” and “Wilson John”, but doesn’t have a version of “Smith John”, I don’t want to find that document.

I think you should use `edge_ngram` filter in your analyzer for indexing and run `match_phrase` query with `standard` analyzer for making queries. You can read more about it [here](https://www.elastic.co/guide/en/elasticsearch/guide/master/_index_time_search_as_you_type.html)

Regarding your second question, can you explain a bit more?

---

<div class="post-metadata">

### Author: ![myronuecker](https://avatars.discourse-cdn.com/v4/letter/m/35a633/32.png) [@myronuecker](https://discuss.elastic.co/u/myronuecker)
#### Post date: [March 18, 2019, 5:26pm UTC](https://discuss.elastic.co/t/phrase-query-with-prefix-produces-0-results/172549/7 "2019-03-18T17:26:57Z")

</div>

I tried your solution using edge\_ngram. What I found is that it prefixes both names. Instead of just finding "smith john" it also found "smithson john". This makes me think that match\_phrase\_prefix is still the better solution for us.

---

<div class="post-metadata">

### Author: ![safwan](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/safwan/32/31879_2.png) [@safwan](https://discuss.elastic.co/u/safwan)
#### Post date: [March 19, 2019, 2:28am UTC](https://discuss.elastic.co/t/phrase-query-with-prefix-produces-0-results/172549/8 "2019-03-19T02:28:57Z")

</div>

Have you used `match` query or `match_phrase` query? You should use `match_phrase` query instead of `match` query.

---

<div class="post-metadata">

### Author: ![myronuecker](https://avatars.discourse-cdn.com/v4/letter/m/35a633/32.png) [@myronuecker](https://discuss.elastic.co/u/myronuecker)
#### Post date: [March 19, 2019, 12:50pm UTC](https://discuss.elastic.co/t/phrase-query-with-prefix-produces-0-results/172549/9 "2019-03-19T12:50:59Z")

</div>

My query was:

```
{
	"query": {
		"match_phrase": {
			"name": "smith john"
		}
	}
}
```

---

<div class="post-metadata">

### Author: ![myronuecker](https://avatars.discourse-cdn.com/v4/letter/m/35a633/32.png) [@myronuecker](https://discuss.elastic.co/u/myronuecker)
#### Post date: [March 21, 2019, 8:38pm UTC](https://discuss.elastic.co/t/phrase-query-with-prefix-produces-0-results/172549/10 "2019-03-21T20:38:37Z")

</div>

I found a post that mentioned the "span\_near" query. That actually seems to work quite well. I had to first convert the terms to lower case since that is what the analyzer is doing when it stores them. Then I had to use "span\_multi" with a prefix query for the final term.

I tried using span\_first, but that doesn't work if there are multiple names indexed into the same field as an array as it will only find the first name in the list.

To get a true "starts with" query I had to index a special character at the beginning of the name. In our system we index "smith john" as "^ smith john" so the prefix query will work as expected.

You end up with a query like this:

```
{
    "query": {
        "span_near": {
            "clauses": [
                {
                    "span_term": {
                        "name": "^"
                    }
                },
                {
                    "span_term": {
                        "name": "smith"
                    }
                },
                {
                    "span_multi": {
                        "match": {
                            "prefix": {
                                "name": "john"
                            }
                        }
                    }
                }
            ],
            "in_order": true
        }
    }
}
```

---

<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: [April 18, 2019, 8:38pm UTC](https://discuss.elastic.co/t/phrase-query-with-prefix-produces-0-results/172549/11 "2019-04-18T20:38:38Z")

</div>

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