Question

Searching for names(text) with spaces in it, causing problem to me, I have mapping similar to

"{"user":{"properties":{"name":{"type":"string"}}}}"

Ideally what it should return and rank results as follows

1) Bring on top names that exact match the search term (highest score)
2) Names that starts with the search term (high score)
3) Names that contains the exact search term as substring (medium score)
4) Names that contains any of the search term token  (lowest score)

Example For following names in elasticsearch

Maaz Tariq
Ahmed Maaz Tariq
Maaz Sheeba
Maaz Bin Tariq
Sana Tariq
Maaz Tariq Ahmed

Searching for "Maaz Tariq" , Results should be in following order

Maaz Tariq (highest score)
Maaz Tariq Ahmed (high score)
Ahmed Maaz Tariq (medium score)
Maaz Bin Tariq  (lowest score)
Maaz Sheeba (lowest score)
Sana Tariq (lowest score)

Can any one point me how and which analyzers to use? and how to rank the search results for names?

Was it helpful?

Solution

You can use the multi field type, a bool query and the custom boost factor query to solve this problem.

Mapping:

{
    "mappings" : {
        "user" : {        
            "properties" : {
                "name": {
                    "type": "multi_field",
                    "fields": {
                        "name": { "type" : "string", "index": "analyzed" },
                        "exact": { "type" : "string", "index": "not_analyzed" }
                    }
                }
            }
        }
    }
}

Query:

{
    "query": {
        "bool": {
            "must": [
                {
                    "match": {
                        "name": "Maaz Tariq"
                    }
                }
            ],
            "should": [
                {
                    "custom_boost_factor": {
                        "query": {
                            "term": {
                                "name.exact": "Maaz Tariq"
                            }
                        },
                        "boost_factor": 15
                    }
                },
                {
                    "custom_boost_factor": {
                        "query": {
                            "prefix": {
                                "name.exact": "Maaz Tariq"
                            }
                        },
                        "boost_factor": 10
                    }
                },
                {
                    "custom_boost_factor": {
                        "query": {
                            "match_phrase": {
                                "name": {
                                    "query": "Maaz Tariq",
                                    "slop": 0
                                }
                            }
                        },
                        "boost_factor": 5
                    }
                }
            ]
        }
    }
}

edit:

As pointed out by javanna, the custom_boost_factor isn't needed.

Query without custom_boost_factor:

{
    "query": {
        "bool": {
            "must": [
                {
                    "match": {
                        "name": "Maaz Tariq"
                    }
                }
            ],
            "should": [
                {
                    "term": {
                        "name.exact": {
                            "value": "Maaz Tariq",
                            "boost": 15
                        }
                    }
                },
                {
                    "prefix": {
                        "name.exact": {
                            "value": "Maaz Tariq",
                            "boost": 10
                        }
                    }
                },
                {
                    "match_phrase": {
                        "name": {
                            "query": "Maaz Tariq",
                            "slop": 0,
                            "boost": 5
                        }
                    }
                }
            ]
        }
    }
}

OTHER TIPS

In case of Java Api, when quering exact strings with spaces use;

CLIENT.prepareSearch(index)
    .setQuery(QueryBuilders.queryStringQuery(wordString)
    .field(fieldName));

In a lot of other queries, you get nothing as result

And from Elasticsearch 1.0:

"title": {
    "type": "multi_field",
    "fields": {
        "title": { "type": "string" },
        "raw":   { "type": "string", "index": "not_analyzed" }
    }
}

became:

"title": {
    "type": "string",
    "fields": {
        "raw":   { "type": "string", "index": "not_analyzed" }
    }
}

https://www.elastic.co/guide/en/elasticsearch/reference/current/multi-fields.html

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top