我们在找出如何最好地管理我们的标记化和未标记化字段以进行搜索和排序时遇到了一些困难。我们的目标非常简单:
我们可以使用动态模板来完成此任务。我们使用默认标记器,自定义ngram标记器和未分析的标记器存储字符串。映射:
curl -XPUT 'http://testServer:9200/test/' -d '{
"settings": {
"analysis": {
"analyzer": {
"my_ngram_analyzer": {
"tokenizer": "my_ngram_tokenizer",
"filter": [
"lowercase"
],
"type" : "custom"
},
"default_search": {
"tokenizer" : "keyword",
"filter" : [
"lowercase"
]
}
},
"tokenizer": {
"my_ngram_tokenizer": {
"type": "nGram",
"min_gram": "3",
"max_gram": "100",
"token_chars": []
}
}
}
},
"mappings": {
"TestObject": {
"dynamic_templates": [
{
"metadata_template": {
"match_mapping_type": "string",
"path_match": "*",
"mapping": {
"type": "multi_field",
"fields": {
"ngram": {
"type": "{dynamic_type}",
"index": "analyzed",
"index_analyzer": "my_ngram_analyzer",
"search_analyzer" : "default_search"
},
"{name}": {
"type": "{dynamic_type}",
"index": "analyzed",
"index_analyzer" : "standard",
"search_analyzer" : "default_search"
},
"sortable": {
"type": "{dynamic_type}",
"index": "analyzed",
"analyzer" : "default_search"
}
}
}
}
}
]
}
}
}'
实际上,我们只保留未分析的字段以进行排序和完全匹配(我们甚至称其为“可排序”。)如果查询是“包含”查询,则这种配置使我们可以轻松地进行部分单词搜索-将“ .ngram”附加到查询目标。我们遇到的问题是决定何时使用“ .sortable”后缀。例如,如果我们收到一个对dateUpdated进行排序的请求,则我们不想使用.sortable,因为该字段是一个日期。如果请求是按“名称”排序,我们确实要使用它,因为该字段是一个字符串,如果我们试图按“价格”进行排序,则不要使用它。
在排序之前检查字段类型的逻辑似乎有点混乱(我们检查模型,而不是在Elasticsearch中检查类型)。总有一个“ .sortable”字段会很好,但是我们可以”不能通过下面的动态模板运行非字符串类型-布尔值和数字不能通过ngram过滤器运行。
是否有人建议我们如何始终有一个“ .sortable”字段进行排序,而无论其类型如何,该字段都不会被标记化?或者,对于您没有遇到的这种问题,您有更好的解决方案吗?提前致谢!
真正归结为的是,我们一直希望在每个映射字段上都有一个“可排序”字段-(我们将其重命名为“未分析”,因为它还有其他用途)。在不为每种类型添加新的动态模板的情况下,执行此操作的真正技巧是制作一个适用于除字符串以外的所有类型的动态模板。为此,您需要设置match_pattern
为正则表达式:
{
"other_types": {
"match_mapping_type": "date|boolean|double|long|integer",
"match_pattern": "regex",
"path_match": ".*",
"mapping": {
"type": "multi_field",
"fields": {
"{name}": {
"type": "{dynamic_type}",
"index": "not_analyzed"
},
"unanalyzed": {
"type": "{dynamic_type}",
"index": "not_analyzed"
}
}
}
}
}
请注意,您还需要对“ path_match”进行一些小的更改-您必须使用真实的正则表达式(而不是ES的“ *”,即“简单”表达式)。
这样做的一个缺点是我们增加了索引的大小-我们将所有这些类型存储了两次。但是出于我们的目的,我们的索引(我们有很多)有很大的增长空间,值得避免在执行排序或完全匹配查询之前总是在每个字段上进行类型查找(始终使用$ {fieldName}。未分析)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句