使用Elasticsearch multi_match搜索含@的邮箱关键词失败求助
Hey there! Let's break down why your search for @gmail.com isn't working and how to fix it.
The Root Problem
Your current multi_match query is struggling because of how Elasticsearch's default tokenizer handles special characters like @. When your emails are indexed, the standard tokenizer splits strings like user@gmail.com into separate tokens (e.g., user, gmail, com)—it treats @ as a separator, so the exact string @gmail.com doesn't exist in your inverted index. That's why your query can't find any matches.
Quick Fixes to Try
1. Use a Wildcard Query (Best for Suffix Matching)
Wildcard queries are perfect for matching patterns like email suffixes. This will directly target the email field and find any entry ending with @gmail.com:
$params = [ 'index' => DATABASE, 'type' => 'XYZ', 'body' => [ 'from' => 0, 'size' => 20, 'query' => [ 'wildcard' => [ 'email' => '*@gmail.com' ] ], 'sort' => ['_score'] ] ];
The * acts as a wildcard to match any characters before @gmail.com.
2. Use the Keyword Subfield (If Available)
If your email field was mapped with a keyword subfield (common in default mappings), you can search against this field to match the full, un-tokenized email string. This is more efficient than wildcard for exact or suffix matches:
$params = [ 'index' => DATABASE, 'type' => 'XYZ', 'body' => [ 'from' => 0, 'size' => 20, 'query' => [ 'wildcard' => [ 'email.keyword' => '*@gmail.com' ] ], 'sort' => ['_score'] ] ];
email.keyword stores the full email as a single token, so the wildcard will work reliably here.
3. Adjust Your Multi-Match Query (Less Ideal, But Possible)
If you really need to use multi_match, target the keyword subfield and use a wildcard in your query. This maintains the multi-field search while fixing the tokenization issue:
$params = [ 'index' => DATABASE, 'type' => 'XYZ', 'body' => [ 'from' => 0, 'size' => 20, 'query' => [ 'multi_match' => [ 'query' => '*@gmail.com', 'fields' => ['email.keyword', '_all'], 'operator' => 'AND' ] ], 'sort' => ['_score'] ] ];
Note: This is less efficient than a direct wildcard on the email field.
Why Your Original Query Failed
- The standard tokenizer splits
@gmail.comintogmailandcom, so there's no token matching@gmail.comin the index. - Using
operator: ANDwith this query means Elasticsearch is looking for fields that contain the non-existent@gmail.comtoken—so no matches are returned.
内容的提问来源于stack exchange,提问作者Shreyas P

