使用单个查询字符串和任意顺序的单词查询多个字段



我认为这个场景一定很常见,但我找不到任何关于如何进行的线索。

我有一个包含单个类型Order的弹性搜索索引。反过来,Order包含Customer信息,例如firstNamelastNamemiddleName(以及它们的级联fullName),例如

"order": {
// other stuff
"customer": {
"firstName": ...,
"lastName": ...,
"middleName": ...,
"fullName": "FirstName MiddleName LastName"
}
}

其目的是提供订单搜索功能,包括按客户姓名进行搜索。弹性的输入总是一个查询字符串,包含用户在搜索框中键入的任何内容。问题是有一些脏数据(例如,缺少firstName、交换了名字和姓氏等),我不能依赖用户总是按特定顺序输入名字。

我已经尝试过用query_string这样的查询来实现这一点:

"query_string": {
"query": "[User Input]*", // note asterisk here
"fields" : ["customer.firstName", "customer.lastName", "customer.middleName"],
"analyzer": "whitespace",
"use_dis_max": true,
"tie_breaker": 0.7,
"analyze_wildcard": true
}

在某些情况下,它在查找结果方面做得很好,但它对脏数据肯定不可靠,例如,如果搜索"John Do"(不是拼写错误),它会找到John Doe的顺序,但如果搜索"Doe John",它会失败。

所需的查询行为类似于多个字段上的match_phrase_prefix,使用whitespace分析器来处理查询,并对来自分析器的每个术语进行前缀。例如,John Doe将变成类似于["John*", "Doe*"]的东西,并分别应用于

  • firstNamelastNamemiddleName字段
  • fullName,允许单个术语按任何顺序出现

我对弹性很陌生,所以我可能缺少一些非常简单的东西,或者没有足够的信心来编写非常复杂的查询。

编辑:索引映射:http://pastebin.com/fuLLgHjB.目标字段尚未分析,因为:(1)我不是进行初始设置的人;(2)我真的不确定应该设置什么字段分析器,所以这是问题的一部分。

Elasticsearch有非常好的默认值。您应该从默认设置开始,只有在某些设置没有按您想要的方式工作时才添加/更改设置。越简单越好。

设置映射时,字符串字段的默认值是分析它们。这是一件好事,因为将字符串分解为标记并进行词干处理,这样您就可以进行部分匹配和模糊匹配。您不需要指定分析器;标准分析仪应该可以正常工作。未分析的字段意味着Elasticsearch不会对字段做任何操作;这对于faceting(按"John"、"Jon"one_answers"Jonathan"中的每一个计算订单数量)之类的事情很有用,但对于一般的全文搜索则不那么有用。如果你真的认为你需要一个未分析的字段版本,你可以将同一个字段包括在内,包括已分析的和未分析的多个字段;有关更多信息,请参阅多字段文档。

这是一个示例映射;您甚至可能不需要生成CCD_ 17字段。

"properties": {
"firstName": { "type": "string" },
"lastName": { "type": "string" },
"middleName": { "type": "string" },
"fullName": { "type": "string" }
}

一旦分析了字段,查询中的术语顺序就不必完全匹配,拼写也不必完美,等等。尝试最简单的查询,它应该会很好地工作:

{
"query": {
"query_string": {
"query": "John Doe",
"fields": [
"firstName",
"middleName",
"lastName"
]
]
}
}
}

如果它没有按照您期望的方式对结果进行排序,您可以尝试用AND替换查询字符串中的非尾随空白,以要求所有术语:John AND Doe

最新更新