# Fuzzy matching against multiple fields

**URL:** <https://discuss.elastic.co/t/fuzzy-matching-against-multiple-fields/4244>\
**Category:** Elasticsearch\
**Created:** [April 17, 2011, 8:23am UTC](https://discuss.elastic.co/t/fuzzy-matching-against-multiple-fields/4244 "2011-04-17T08:23:03Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![pcdinh](https://avatars.discourse-cdn.com/v4/letter/p/76d3ee/32.png) [@pcdinh](https://discuss.elastic.co/u/pcdinh)\
**Post date:** [April 17, 2011, 8:23am UTC](https://discuss.elastic.co/t/fuzzy-matching-against-multiple-fields/4244/1 "2011-04-17T08:23:03Z")

</div>

Hi all,

I want to make a fuzzy query that is expected to work on multiple  
fields. What is the correct way to do it?

I made the following queries [https://gist.github.com/923848](https://gist.github.com/923848) but it  
does not work

Thanks

pcdinh

---

<div class="post-metadata">

**Author:** ![Clinton\_Gormley](https://avatars.discourse-cdn.com/v4/letter/c/50afbb/32.png) [@Clinton\_Gormley](https://discuss.elastic.co/u/Clinton_Gormley)\
**Post date:** [April 17, 2011, 9:31am UTC](https://discuss.elastic.co/t/fuzzy-matching-against-multiple-fields/4244/2 "2011-04-17T09:31:46Z")

</div>

Hi pcdinh

> I want to make a fuzzy query that is expected to work on multiple  
> fields. What is the correct way to do it?
> 
> I made the following queries [gist:923848 · GitHub](https://gist.github.com/923848) but it  
> does not work

The easiest way to do it is to use the ~ operator in the query string,  
for instance:

curl -XGET '[http://127.0.0.1:9200/accdev/exp/\_search?pretty=1](http://127.0.0.1:9200/accdev/exp/_search?pretty=1)' -d '  
{  
"query" : {  
"query\_string" : {  
"query" : "username:pcdinh~0.5 fullname\_idx:pcdinh~0.1^3",  
"fuzzy\_prefix\_length" : 1  
}  
}  
}  
'

For more on the Lucene query string syntax, see:  
[http://lucene.apache.org/java/3\_0\_0/queryparsersyntax.html](http://lucene.apache.org/java/3_0_0/queryparsersyntax.html)

The query string is a bit less configurable than a fuzzy query (for  
instance you can't specify a per-field fuzzy\_prefix\_length.

In order to use the fuzzy query against two different fields, you need  
to use two fuzzy queries:

```
        {
           "fuzzy" : {
              "username" : {
                 "min_similarity" : 0.5,
                 "boost" : 1,
                 "value" : "pcdin",
                 "prefix_length" : 0
              }
           }
        },
        {
           "fuzzy" : {
              "fullname_idx" : {
                 "min_similarity" : 0.1,
                 "boost" : 3,
                 "value" : "pcdinh",
                 "prefix_length" : 1
              }
           }
        }

```

But you need to combine these two queries somehow. Your options are to  
wrap them in either a 'bool' query, or a 'dis\_max' query:

bool:[Elasticsearch Platform — Find real-time answers at scale | Elastic](http://www.elasticsearch.org/guide/reference/query-dsl/bool-query.html)

curl -XGET '[http://127.0.0.1:9200/accdev/exp/\_search?pretty=1](http://127.0.0.1:9200/accdev/exp/_search?pretty=1)' -d '  
{  
"query" : {  
"bool" : {  
"should" : [  
FUZZY QUERIES HERE  
]  
}  
}  
}  
'

dis\_max:[Elasticsearch Platform — Find real-time answers at scale | Elastic](http://www.elasticsearch.org/guide/reference/query-dsl/dis-max-query.html)

curl -XGET '[http://127.0.0.1:9200/accdev/exp/\_search?pretty=1](http://127.0.0.1:9200/accdev/exp/_search?pretty=1)' -d '  
{  
"query" : {  
"dis\_max" : {  
"queries" : [  
FUZZY QUERIES HERE  
],  
"tie\_breaker" : 0.7  
}  
}  
}  
'

The difference between bool and dis\_max is how it combines the score if  
both queries match. The bool query would add both their scores  
together. The dis\_max would return the better score.

In your case, where you're searching for a matching user, it would  
probably make sense to use the bool query, so the full query would look  
like this:

curl -XGET '[http://127.0.0.1:9200/accdev/exp/\_search?pretty=1](http://127.0.0.1:9200/accdev/exp/_search?pretty=1)' -d '  
{  
"query" : {  
"bool" : {  
"should" : [  
{  
"fuzzy" : {  
"username" : {  
"min\_similarity" : 0.5,  
"boost" : 1,  
"value" : "pcdin",  
"prefix\_length" : 0  
}  
}  
},  
{  
"fuzzy" : {  
"fullname\_idx" : {  
"min\_similarity" : 0.1,  
"boost" : 3,  
"value" : "pcdinh",  
"prefix\_length" : 1  
}  
}  
}  
]  
}  
}  
}  
'

Alternatively, unless you have disabled it, the values for both username  
and fullname\_idx are also indexed in the \_all field. So, (sacrificing  
the per-field customizations) you could just do:

curl -XGET '[http://127.0.0.1:9200/accdev/exp/\_search?pretty=1](http://127.0.0.1:9200/accdev/exp/_search?pretty=1)' -d '  
{  
"query" : {  
"fuzzy" : {  
"\_all" : {  
"min\_similarity" : 0.1,  
"value" : "pcidnh"  
}  
}  
}  
}  
'

Or even:

curl -XGET '[http://127.0.0.1:9200/accdev/exp/\_search?pretty=1](http://127.0.0.1:9200/accdev/exp/_search?pretty=1)' -d '  
{  
"query" : {  
"field" : {  
"\_all" : "pcidnh~0.1"  
}  
}  
}  
'

clint

---

<div class="post-metadata">

**Author:** ![pcdinh](https://avatars.discourse-cdn.com/v4/letter/p/76d3ee/32.png) [@pcdinh](https://discuss.elastic.co/u/pcdinh)\
**Post date:** [April 19, 2011, 8:30am UTC](https://discuss.elastic.co/t/fuzzy-matching-against-multiple-fields/4244/3 "2011-04-19T08:30:04Z")

</div>

Hi Clinton,

Thank a lot for your excellent answer. I will use Lucene syntax to  
reduce request bandwidth to ES server.

Also, it is great to see your answer part of ES documentation

Regards,

pcdinh

On 17 Tháng Tư, 16:31, Clinton Gormley [clin...@iannounce.co.uk](mailto:clin...@iannounce.co.uk)  
wrote:

> Hi pcdinh
> 
> > I want to make a fuzzy query that is expected to work on multiple  
> > fields. What is the correct way to do it?
> 
> > I made the following querieshttps://gist.github.com/923848but it  
> > does not work
> 
> The easiest way to do it is to use the ~ operator in the query string,  
> for instance:
> 
> curl -XGET '[http://127.0.0.1:9200/accdev/exp/\_search?pretty=1](http://127.0.0.1:9200/accdev/exp/_search?pretty=1)' -d '  
> {  
> "query" : {  
> "query\_string" : {  
> "query" : "username:pcdinh~0.5 fullname\_idx:pcdinh~0.1^3",  
> "fuzzy\_prefix\_length" : 1  
> }  
> }}
> 
> '
> 
> For more on the Lucene query string syntax, see:[Apache Lucene - Query Parser Syntax](http://lucene.apache.org/java/3_0_0/queryparsersyntax.html)
> 
> The query string is a bit less configurable than a fuzzy query (for  
> instance you can't specify a per-field fuzzy\_prefix\_length.
> 
> In order to use the fuzzy query against two different fields, you need  
> to use two fuzzy queries:
> 
> ```
> {
> "fuzzy" : {
> "username" : {
> "min_similarity" : 0.5,
> "boost" : 1,
> "value" : "pcdin",
> "prefix_length" : 0
> }
> }
> },
> {
> "fuzzy" : {
> "fullname_idx" : {
> "min_similarity" : 0.1,
> "boost" : 3,
> "value" : "pcdinh",
> "prefix_length" : 1
> }
> }
> }
> 
> ```
> 
> But you need to combine these two queries somehow. Your options are to  
> wrap them in either a 'bool' query, or a 'dis\_max' query:
> 
> bool:[Elasticsearch Platform — Find real-time answers at scale | Elastic](http://www.elasticsearch.org/guide/reference/query-dsl/bool-query.html)
> 
> curl -XGET '[http://127.0.0.1:9200/accdev/exp/\_search?pretty=1](http://127.0.0.1:9200/accdev/exp/_search?pretty=1)' -d '  
> {  
> "query" : {  
> "bool" : {  
> "should" : [  
> FUZZY QUERIES HERE  
> ]  
> }  
> }}
> 
> '
> 
> dis\_max:[Elasticsearch Platform — Find real-time answers at scale | Elastic](http://www.elasticsearch.org/guide/reference/query-dsl/dis-max-query)....
> 
> curl -XGET '[http://127.0.0.1:9200/accdev/exp/\_search?pretty=1](http://127.0.0.1:9200/accdev/exp/_search?pretty=1)' -d '  
> {  
> "query" : {  
> "dis\_max" : {  
> "queries" : [  
> FUZZY QUERIES HERE  
> ],  
> "tie\_breaker" : 0.7  
> }  
> }}
> 
> '
> 
> The difference between bool and dis\_max is how it combines the score if  
> both queries match. The bool query would add both their scores  
> together. The dis\_max would return the better score.
> 
> In your case, where you're searching for a matching user, it would  
> probably make sense to use the bool query, so the full query would look  
> like this:
> 
> curl -XGET '[http://127.0.0.1:9200/accdev/exp/\_search?pretty=1](http://127.0.0.1:9200/accdev/exp/_search?pretty=1)' -d '  
> {  
> "query" : {  
> "bool" : {  
> "should" : [  
> {  
> "fuzzy" : {  
> "username" : {  
> "min\_similarity" : 0.5,  
> "boost" : 1,  
> "value" : "pcdin",  
> "prefix\_length" : 0  
> }  
> }  
> },  
> {  
> "fuzzy" : {  
> "fullname\_idx" : {  
> "min\_similarity" : 0.1,  
> "boost" : 3,  
> "value" : "pcdinh",  
> "prefix\_length" : 1  
> }  
> }  
> }  
> ]  
> }  
> }}
> 
> '
> 
> Alternatively, unless you have disabled it, the values for both username  
> and fullname\_idx are also indexed in the \_all field. So, (sacrificing  
> the per-field customizations) you could just do:
> 
> curl -XGET '[http://127.0.0.1:9200/accdev/exp/\_search?pretty=1](http://127.0.0.1:9200/accdev/exp/_search?pretty=1)' -d '  
> {  
> "query" : {  
> "fuzzy" : {  
> "\_all" : {  
> "min\_similarity" : 0.1,  
> "value" : "pcidnh"  
> }  
> }  
> }}
> 
> '
> 
> Or even:
> 
> curl -XGET '[http://127.0.0.1:9200/accdev/exp/\_search?pretty=1](http://127.0.0.1:9200/accdev/exp/_search?pretty=1)' -d '  
> {  
> "query" : {  
> "field" : {  
> "\_all" : "pcidnh~0.1"  
> }  
> }}
> 
> '
> 
> clint

---

<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 6, 2017, 4:08am UTC](https://discuss.elastic.co/t/fuzzy-matching-against-multiple-fields/4244/4 "2017-07-06T04:08:06Z")

</div>


