Elasticsearch找到子域名

时间:2018-05-09 09:03:43

标签: php elasticsearch

我尝试在elasticsearch中按主域查找子域名。 我添加了一些有弹性的域名:

 $domains = [
    'site.com',
    'ns1.site.com',
    'ns2.site.com',
    'test.main.site.com',
    'sitesite.com',
    'test-site.com',
];
foreach ($domains as $domain) {
    $params = [
        'index' => 'my_index',
        'type' => 'my_type',
        'body' => ['domain' => $domain],
    ];
    $client->index($params);
}

然后我尝试搜索:

$params = [
    'index' => 'my_index',
    'type' => 'my_type',
    'body' => [
        'query' => [
            'wildcard' => [
                'domain' => [
                    'value' => '.site.com',
                ],
            ],
        ],
    ],
];
$response = $client->search($params);
但是一无所获。 :(

我的映射是: https://pastebin.com/raw/k9MzjJUM

有任何想法要解决它吗?

由于

1 个答案:

答案 0 :(得分:0)

你快到了,只缺少几件事。

如何制作“以...结尾”查询?

在查询中添加*就足够了(这就是为什么会调用此查询wildcard):

POST my_index/my_type/_search
{
    "query": {
        "wildcard" : { "domain" : "*.site.com" }
    }
}

这会给你以下结果:

{
  ...
  "hits": {
    "total": 1,
    "max_score": 1,
    "hits": [
      {
        "_index": "my_index",
        "_type": "my_type",
        "_id": "RoE8VGMBRuo1XmkIXhp0",
        "_score": 1,
        "_source": {
          "domain": "test.main.site.com"
        }
      }
    ]
  }
}

似乎工作,但我们只得到一个结果(不是全部)。

为什么它不返回所有匹配的文件?

返回您的映射,字段domain的类型为text

PUT my_index
{
  "mappings": {
    "my_type": {
      "properties": {
        "domain": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        }
      }
    }
  }
}

这意味着该字段的内容将被标记化并小写(使用standard分析器)。您可以使用_analyze API查看哪些令牌可以实际搜索,如下所示:

POST _analyze
{
  "text": "test.main.site.com"
}

{
  "tokens": [
    {
      "token": "test.main.site.com",
      "start_offset": 0,
      "end_offset": 18,
      "type": "<ALPHANUM>",
      "position": 0
    }
  ]
}

这就是wildcard查询可以匹配test.main.site.com的原因。

如果我们选择n1.site.com怎么办?

POST _analyze
{
  "text": "n1.site.com"
}

{
  "tokens": [
    {
      "token": "n1",
      "start_offset": 0,
      "end_offset": 2,
      "type": "<ALPHANUM>",
      "position": 0
    },
    {
      "token": "site.com",
      "start_offset": 3,
      "end_offset": 11,
      "type": "<ALPHANUM>",
      "position": 1
    }
  ]
}

如您所见,没有以.site.com结尾的令牌(请注意.之前的site.com)。

幸运的是,您的映射已经能够返回所有结果。

如何返回“以...结尾”查询的所有结果?

您可以使用keyword字段,该字段使用确切的值进行查询:

POST my_index/my_type/_search
{
    "query": {
        "wildcard" : { "domain.keyword" : "*.site.com" }
    }
}

这会给你以下结果:

{
  "hits": {
    "total": 3,
    "max_score": 1,
    "hits": [
      {
        "_index": "my_index",
        "_type": "my_type",
        "_id": "RoE8VGMBRuo1XmkIXhp0",
        "_score": 1,
        "_source": {
          "domain": "test.main.site.com"
        }
      },
      {
        "_index": "my_index",
        "_type": "my_type",
        "_id": "Q4E8VGMBRuo1XmkIFRpy",
        "_score": 1,
        "_source": {
          "domain": "ns1.site.com"
        }
      },
      {
        "_index": "my_index",
        "_type": "my_type",
        "_id": "RYE8VGMBRuo1XmkIORqG",
        "_score": 1,
        "_source": {
          "domain": "ns2.site.com"
        }
      }
    ]
  }
}

这是“以”类似查询结束的最佳方式吗?

实际上,没有。 wildcard次查询can be very slow

  

请注意,此查询可能很慢,因为它需要迭代多次   条款。为了防止极慢的通配符查询,使用通配符   术语不应以其中一个通配符*或?开头。

为了获得最佳性能,在您的情况下,我建议您创建另一个字段higherLevelDomains,并手动从原始字段中提取更高级别的域。该文件可能如下所示:

POST my_index/my_type
{
  "domain": "test.main.site.com",
  "higherLevelDomains": [
    "main.site.com",
    "site.com",
    "com"
  ]
}

这将允许您使用term查询:

POST my_index/my_type/_search
{
    "query": {
        "term" : { "higherLevelDomains.keyword" : "site.com" }
    }
}

这可能是您可以使用Elasticsearch进行此类任务的最有效查询。

希望有所帮助!