Elasticsearch通过主域名查找子域名失败问题求助
嘿,我来帮你捋一捋这个问题的根源和解决办法~
首先得搞清楚为什么你的wildcard查询没返回结果:你的domain字段用的是text类型,默认的standard分词器会把域名拆成单个单词(比如ns1.site.com会被拆成["ns1", "site", "com"]),而wildcard查询是针对倒排索引里的词条进行匹配的,你用.site.com作为匹配值,倒排索引里根本没有这个词条,自然查不到结果。
接下来给你几个可行的解决思路,优先推荐第一个,简单直接:
思路1:使用keyword子字段(最快捷有效)
text类型的字段默认会自动生成一个keyword子字段(从你的映射信息来看,这个子字段是存在的),它会保存原始的完整域名字符串,不会被分词,正好适合做后缀匹配。
具体操作:
修改你的查询语句,把匹配的字段从domain换成domain.keyword,同时调整wildcard的匹配值(原来的.site.com只会匹配精确等于这个值的域名,你索引里没有,所以要加*匹配前缀):
$params = [ 'index' => 'my_index', 'type' => 'my_type', 'body' => [ 'query' => [ 'wildcard' => [ 'domain.keyword' => [ 'value' => '*.site.com', // 匹配所有以 .site.com 结尾的子域名 ], ], ], ], ]; $response = $client->search($params);
如果连主域名site.com也想匹配到,可以把value改成*site.com。
思路2:自定义域名专用分词器
如果需要更灵活的域名查询(比如单独匹配某个子域层级),可以自定义一个按.拆分的分词器,把每个子域都作为独立词条存储。
具体操作:
- 先删除旧索引(如果数据可以重新导入),创建带自定义分词器的新索引:
PUT /my_index { "settings": { "analysis": { "analyzer": { "domain_analyzer": { "tokenizer": "domain_tokenizer" } }, "tokenizer": { "domain_tokenizer": { "type": "pattern", "pattern": "\\." } } } }, "mappings": { "my_type": { "properties": { "domain": { "type": "text", "analyzer": "domain_analyzer", "fields": { "keyword": { "type": "keyword" } } } } } } }
- 重新导入所有域名数据
- 之后你可以用
match查询某个子域,或者继续用wildcard做后缀匹配,不过这种方式更适合复杂的域名层级查询。
思路3:避免踩坑的小提醒
不要直接用text字段做后缀匹配:因为分词后的词条是零散的单词,比如用suffix查询site,会匹配到sitesite.com里的site词条,完全不符合你要的域名后缀匹配需求,所以优先用keyword子字段方案。
总结一下,最快解决问题的方式就是用domain.keyword配合*.site.com的wildcard查询,马上就能得到你想要的子域名结果啦~
内容的提问来源于stack exchange,提问作者Joe Brew

