弹性搜索空间

I have a Elasticsearch setup which will allow user to search indexes as wild cards.

array:3 [
 "index" => "users"
 "type" => "user"
 "body" => array:4 [
 "from" => 0
 "size" => 25
 "sort" => array:1 [
  1 => array:1 [
    "order" => "asc"
  ]
]
"query" => array:1 [
  "bool" => array:1 [
    "should" => array:1 [
      0 => array:1 [
        0 => array:1 [
          "wildcard" => array:1 [
            "full_name" => "john doe"
          ]
        ]
      ]
    ]
  ]
]
]
]

when I pass this array to search function, it is returning an empty array. But there is a document related to "John Doe" and when I run "full_name" => "john" search is returning the document.

I feel that the problem is with the space.

{
"users": {
"user": {
  "properties": {

    "address": {
      "type": "string"
    },
    "full_name": {
      "type": "string"
    },
    "industry_name": {
      "type": "string"
    }
  }
}

} }

Assuming field full_name is analyzed by elasticsearch.

The problem in your case is fact that wildcard query doesn't analyze search string

Matches documents that have fields matching a wildcard expression (not analyzed).

In you case it means, that elasticsearch stored john and doe tokens in inverted index, but wildcard query is searching for john doe token, and it fails.

What you can do about this:

  1. Change index mapping, so full_name filed is not analyzed anymore. Note: you will have to search for John Doe to get match, because value wasn't analyzed so john doe won't match.
  2. You can improve first solution, just by leaving full_name analyzed, but with custom analyzer(wildcard, lowercase). It will allow you to search for text john doe or John Doe.

    {
        "settings" : {
            "index" : {
                "analysis" : {
                    "analyzer" : {
                        "lowercase_analyzer" : {
                            "tokenizer" : "keyword",
                            "filter" : [
                                "lowercase"
                            ],
                            "type" : "custom"
                        }
                    }
                }
            }
        },
        "mappings" : {
            "user" : {
                "properties" : {
                    "id" : {
                        "type" : "integer"
                    },
                    "fullName" : {
                        "analyzer" : "lowercase_analyzer",
                        "type" : "string"
                    }
                }
            }
        }
    }
    
  3. You can take advantage of multi field, and search against raw field.

    "full_name.raw" => "John Doe"
    

Hope it will help you handle your use case.

UPDATE

Here you can find more information how to control index mapping.

I think standard tokenizer will be applied by default.

In that case, it will consider the text john doe as phrase.

So try phrase search

"full_name" => "\"john doe\""

If you want to consider spaces you could do something like:

{
    "match" : {
         "full_name" : {
            "query" : "john doe",
            "operator" : "and",
            "zero_terms_query": "all"
        }
    }
}

check this: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html