ElasticSearch通过完全匹配搜索电子邮件

时间:2016-07-07 13:13:09

标签: elasticsearch

我需要通过电子邮件搜索联系人。根据{{​​3}},实现这一目标的最佳方法是使用uax_url_email标记生成器。这是我的索引设置:

settings: {
  index: {
    creation_date: "1467895098804",
    analysis: {
      analyzer: {
        email: {
          type: "custom",
          tokenizer: "uax_url_email"
        }
      }
    },
    number_of_shards: "5",
    number_of_replicas: "1",
    uuid: "wL0P6OIaQqqYpFDvIHArTw",
    version: {
      created: "2030399"
    }
  }
}

和映射:

contact: {
  dynamic: "false",
  properties: {
    contact_status: {
      type: "string"
    },
    created_at: {
      type: "date",
      format: "strict_date_optional_time||epoch_millis"
    },
    email: {
      type: "string"
    },
    id: {
      type: "long"
    },
    mailing_ids: {
      type: "long"
    },
    subscription_status: {
      type: "string"
    },
    type_ids: {
      type: "long"
    },
    updated_at: {
      type: "date",
      format: "strict_date_optional_time||epoch_millis"
    },
    user_id: {
      type: "long"
    }
  }
}

创建索引后,我已插入两个文档:

curl -X PUT 'localhost:9200/contacts/contact/1' -d '{"contact_status": "confirmed", "email": "example@gmail.com", "id": "1", "user_id": "1", "subscription_status": "on"}'

curl -X PUT 'localhost:9200/contacts/contact/2' -d '{"contact_status": "confirmed", "email": "example@yahoo.com", "id": "2", "user_id": "2", "subscription_status": "on"}'

然后我尝试通过电子邮件以不同方式搜索联系人:

curl -X POST 'localhost:9200/contacts/_search?pretty' -d '{"query": {"bool": {"must": [ {"match": {"_all": { "query": "example@google.com", "analyzer": "email" } } } ] } } }'

我希望得到1个id = 1的结果,但得到空的命中:

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 0,
    "max_score" : null,
    "hits" : [ ]
  }
}

我测试的下一个搜索查询是:

curl -X POST 'localhost:9200/contacts/_search?pretty' -d '{"query": {"bool": {"must": [ {"match": {"_all": { "query": "example@google", "analyzer": "email" } } } ] } } }'

返回了2个结果:

{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 0.016878016,
    "hits" : [ {
      "_index" : "contacts",
      "_type" : "contact",
      "_id" : "2",
      "_score" : 0.016878016,
      "_source" : {
        "contact_status" : "confirmed",
        "email" : "example@yahoo.com",
        "id" : "2",
        "user_id" : "2",
        "subscription_status" : "on"
      }
    }, {
      "_index" : "contacts",
      "_type" : "contact",
      "_id" : "1",
      "_score" : 0.016878016,
      "_source" : {
        "contact_status" : "confirmed",
        "email" : "example@gmail.com",
        "id" : "1",
        "user_id" : "1",
        "subscription_status" : "on"
      }
    } ]
  }
}

但是据您所知,我希望在搜索结果中获得1个文档。我做错了什么?

2 个答案:

答案 0 :(得分:2)

这就是发生的事情:

&#34; uax_url_email&#34; tokenizer等于&#39;标准&#34; tokenizer(意思是它会删除&#34; @&#34;)除非它得到"<text>@<text>.<text>"的模式,在这种情况下它不会删除&#34; @&#34;但将整个电子邮件地址作为一个标记。

现在,在索引时间,您已定义&#34;电子邮件&#34; field as&#34; string&#34;默认为&#34;标准&#34; tokenizer,意思是 - 您的地址被标记为 2 令牌:&#34; example&#34;和&#34; gmail.com&#34;!在搜索时间,您定义了&#34;电子邮件&#34; tokenizer,意思是你的(第一个)查询&#34; example@google.com"根本没有被标记化(因为它变成了一个电子邮件模式)因此它既不匹配&#34;例如&#34;或&#34; gmail.com&#34; (和雅虎一样)。 在您的第二个查询中,您搜索了&#34;示例@ google&#34; - 这并不属于整个电子邮件模式,因此电子邮件令牌化程序可以作为&#34;标准&#34; tokenizer意味着它会削减&#34; @&#34;和标记化&#34;示例&#34;和#34; google&#34;在你的索引中寻找任何一个。由于示例已在您的2个文档中编入索引 - 它适合两者!

如果您希望只能匹配&#34;示例&#34;您的部分地址 - 您无法使用&#34;电子邮件&#34;分析仪在搜索时! 无论如何,大多数情况下,您不应该从索引分析器 更改搜索分析器!

请注意&#34;标准&#34;分析仪不会削减&#34; gmail.com&#34;分为2个令牌!

答案 1 :(得分:0)

使用它来发出您的请求?对我有用

GET my_index/_search
{
    "query": {
        "match_phrase_prefix" : {
            "email": "valery@gmail.com"
        }
    }
}

您将获得预期的结果