当我的访问者使用我们的搜索功能时,我想为他们提供最好的结果。为此,我想解释搜索查询。
例如,用户搜索“120 厘米儿童的红色床”
我想将其解释如下:
类别过滤器是“床”和“儿童”颜色过滤器是红色尺寸过滤器是 120 厘米
是否有适用于 Elasticsearch 的工具?在 Elasticsearch 之前我需要 NLP 吗?
当我的访问者使用我们的搜索功能时,我想为他们提供最好的结果。为此,我想解释搜索查询。
例如,用户搜索“120 厘米儿童的红色床”
我想将其解释如下:
类别过滤器是“床”和“儿童”颜色过滤器是红色尺寸过滤器是 120 厘米
是否有适用于 Elasticsearch 的工具?在 Elasticsearch 之前我需要 NLP 吗?
Elasticsearch 本身非常强大,并且非常有能力将最相关的结果返回到全文搜索查询,前提是数据被充分索引和查询。
在后台,它总是为全文搜索执行文本分析text
(对于 type 的字段)。文本分析器由字符过滤器、标记器和标记过滤器组成。
例如,同义词标记过滤器可以在用户查询中替换kids
为。children
除此之外,现代网站上的搜索查询通常通过 UI 中的类别选择器来实现,这可以通过keyword
Elasticsearch 的查询字段轻松实现。
正确建模数据并调整其索引以实现您需要的搜索可能就足够了 - 如果这还不够,您可以随时在客户端添加一些额外的类似 NLP 的逻辑层,就像 @2ps 建议的那样。
现在让我展示一个玩具示例,说明您可以使用synonym
令牌过滤器和copy_to
功能实现什么。
假设我们的产品具有以下属性:Category
、Color
和Size.LengthCM
。
映射将类似于:
PUT /my_index
{
"mappings": {
"properties": {
"Category": {
"type": "keyword",
"copy_to": "DescriptionAuto"
},
"Color": {
"type": "keyword",
"copy_to": "DescriptionAuto"
},
"Size": {
"properties": {
"LengthCM": {
"type": "integer",
"copy_to": "DescriptionAuto"
}
}
},
"DescriptionAuto": {
"type": "text",
"analyzer": "MySynonymAnalyzer"
}
}
},
"settings": {
"index": {
"analysis": {
"analyzer": {
"MySynonymAnalyzer": {
"tokenizer": "standard",
"filter": [
"MySynonymFilter"
]
}
},
"filter": {
"MySynonymFilter": {
"type": "synonym",
"lenient": true,
"synonyms": [
"kid, kids => children"
]
}
}
}
}
}
}
请注意,我们keyword
为字段Category
和选择了类型Color
。
现在,这些copy_to
和synonym
呢?
copy_to
做什么?每次我们发送一个索引对象到我们的索引中,关键字字段的值Category
将被复制到一个全文字段中DescritpionAuto
。这就是这样copy_to
做的。
synonym
做什么?要启用synonym
我们需要定义一个自定义分析器,请参阅MySynonymAnalyzer
我们在"settings"
上面定义的。
粗略地说,它将用=>
右侧的标记替换与左侧匹配的每个标记。
让我们插入一些示例文档:
POST /my_index/_doc
{
"Category": [
"beds",
"adult"
],
"Color": "red",
"Size": {
"LengthCM": 150
}
}
POST /my_index/_doc
{
"Category": [
"beds",
"children"
],
"Color": "red",
"Size": {
"LengthCM": 120
}
}
POST /my_index/_doc
{
"Category": [
"couches",
"adult",
"family"
],
"Color": "blue",
"Size": {
"LengthCM": 200
}
}
POST /my_index/_doc
{
"Category": [
"couches",
"adult",
"family"
],
"Color": "red",
"Size": {
"LengthCM": 200
}
}
如您所见,DescriptionAuto
原始文档中不存在 - 尽管copy_to
我们将能够查询它。
让我们看看如何。
query_string
现在我们可以通过一个简单的查询来尝试我们的索引:
POST /my_index/_doc/_search
{
"query": {
"query_string": {
"query": "red beds for kids 120cm",
"default_field": "DescriptionAuto"
}
}
}
结果将如下所示:
"hits": {
...
"max_score": 2.3611186,
"hits": [
{
...
"_score": 2.3611186,
"_source": {
"Category": [
"beds",
"children"
],
"Color": "red",
"Size": {
"LengthCM": 120
}
}
},
{
...
"_score": 1.0998137,
"_source": {
"Category": [
"beds",
"adult"
],
"Color": "red",
"Size": {
"LengthCM": 150
}
}
},
{
...
"_score": 0.34116736,
"_source": {
"Category": [
"couches",
"adult",
"family"
],
"Color": "red",
"Size": {
"LengthCM": 200
}
}
}
]
}
带有类别beds
和children
颜色的文档red
位于顶部。而且它的相关性得分是其后续的两倍!
通过分析 API很容易做到:
POST /my_index/_analyze
{
"text": "red bed for kids 120cm",
"analyzer": "MySynonymAnalyzer"
}
{
"tokens": [
{
"token": "red",
"start_offset": 0,
"end_offset": 3,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "bed",
"start_offset": 4,
"end_offset": 7,
"type": "<ALPHANUM>",
"position": 1
},
{
"token": "for",
"start_offset": 8,
"end_offset": 11,
"type": "<ALPHANUM>",
"position": 2
},
{
"token": "children",
"start_offset": 12,
"end_offset": 16,
"type": "SYNONYM",
"position": 3
},
{
"token": "120cm",
"start_offset": 17,
"end_offset": 22,
"type": "<ALPHANUM>",
"position": 4
}
]
}
如您所见,没有 token kids
,但有 token children
。
附带说明一下,在此示例中,Elasticsearch 无法解析床的大小:token120cm
不匹配任何内容,因为所有大小都是整数,例如120
,150
等。需要进行另一层调整120
从120cm
令牌中提取。
我希望这可以让您了解 Elasticsearch 的内置文本分析功能可以实现什么!