Search code examples
elasticsearchwildcardelasticsearch-dslelasticsearch-query

Could I combine wildcard and fulltext search in Elasticsearch?


For example, I have some titles data in Elasticsearch likes this,
gamexxx_nightmare,
gamexxx_little_guy

Then I input
game => search out gamexxx_nightmare and gamexxx_little_guy
little guy => search out gamexxx_little_guy ?

first I think I will use a wildcard to make game match gamexxx, the second it is fulltext search? How to combine them in one DSL??


Solution

  • While Jaspreet's answer is right but doesn't combine both the requirements in one query DSL as asked by OP in his question How to combine them in one DSL??.

    It's an enhancement to Jaspreet's solution as I am also not using the wild-card and even avoiding the n-gram analyzer which is too costly(increases the index size) and requires re-indexing if requirement changes.

    One Search query to combine both the requirement can be done as below:

    Index mapping

    {
        "settings": {
            "analysis": {
                "analyzer": {
                    "my_analyzer": {
                        "tokenizer": "standard",
                        "char_filter": [
                            "replace_underscore" -->note this
                        ]
                    }
                },
                "char_filter": {
                    "replace_underscore": {
                        "type": "mapping",
                        "mappings": [
                            "_ => \\u0020"
                        ]
                    }
                }
            }
        },
        "mappings": {
            "properties": {
                "title": {
                    "type": "text",
                    "analyzer" : "my_analyzer"
                }
            }
        }
    }
    

    Index your sample docs

    {
       "title" : "gamexxx_little_guy"
    }
    
    And
    
    {
       "title" : "gamexxx_nightmare"
    }
    

    Single Search query

    {
        "query": {
            "bool": {
                "must": [ --> note this
                    {
                        "bool": {
                            "must": [
                                {
                                    "prefix": {
                                        "title": {
                                            "value": "game"
                                        }
                                    }
                                }
                            ]
                        }
                    },
                    {
                        "bool": {
                            "must": [
                                {
                                    "match": {
                                        "title": {
                                            "query": "little guy"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                ]
            }
        }
    }
    

    Result

     {
            "_index": "so-46873023",
            "_type": "_doc",
            "_id": "2",
            "_score": 2.2814486,
            "_source": {
               "title": "gamexxx_little_guy"
            }
         }
    

    Important points:

    1. The first part of the query is prefix query, which would match the game in both the documents. (This would avoid costly regex).
    2. The second part is allowing the full-text search, to enable this, I used custom analyzer which replaces the _ with whitespace, so you don't need expensive (n-grams in index) and simple match query would fetch the results.
    3. Above query, returns result matching both the criteria, you can change the high level, bool clause to should from must if, you want to return matching any criteria.