我正在构建一个分析器,以对术语进行部分搜索。所以我想在索引时间使用2-5 ngram tokenzier,在搜索时使用5-5 ngram。
在索引时间使用2-5个ngram的合理性是长度2的部分项查询应匹配。
在搜索时,如果搜索词的长度小于5,则可以直接在倒排索引中搜索该词。如果len大于5,则该词用5克标记,如果所有标记都匹配,则匹配。
但是,在Elastic中,如果查询词的长度小于5,则使用5-5 ngram tokenziser不会创建任何令牌。 解决方案可能是在搜索时使用2-5令牌生成器,与索引编制相同,但这将导致搜索所有2grams,3grams和4grams令牌,这是没有用的...(5grams令牌就足够了)
这是我当前的索引映射:
{
"settings" : {
"analysis":{
"analyzer":{
"index_partial":{
"type":"custom",
"tokenizer":"2-5_ngram_token"
},
"search_partial":{
"type":"custom",
"tokenizer": "5-5_ngram_token"
}
},
"tokenizer":{
"2-5_ngram_token": {
"type":"nGram",
"min_gram":"2",
"max_gram":"5"
},
"5-5_ngram_token": {
"type":"nGram",
"min_gram":"5",
"max_gram":"5"
}
}
}
},
"mappings": {
"properties": {
"name": {
"type": "keyword"
},
"name_trans": {
"type": "text",
"fields": {
"partial": {
"type":"text",
"analyzer":"index_partial",
"search_analyzer":"search_partial"
}
}
}
}
}
}
所以我的问题是:如果搜索查询的长度小于5,如何创建不执行操作的分析器?如果长度大于5,则创建5克令牌?
----------------------使用解决方案进行更新-------------------- ---
如果len <5且len> = 5则5-5ngram,似乎无法创建不操作的分析器。
围绕执行部分解决方案有两种方法:
1-如@Amit Khandelwal所述,一种解决方案是在索引时间使用max ngram。如果您的字段最多有30个字符,请使用带有ngram 2-30的令牌生成器,并在搜索时搜索准确的字词,而不用ngram分析器对其进行处理(通过字词查询或将搜索分析仪设置为关键字)。 / p>
该解决方案的缺点是,根据最大长度,它可能导致巨大的倒排索引。
2-其他解决方案是创建两个字段: -一种用于简短搜索查询词的词,可以直接在反向索引中查找,而无需标记 -一个较长的搜索查询词,应标记化 根据搜索查询词的长度,搜索应在这两个字段之一中进行
以下是我用于解决方案2的映射(我选择的短期和长期之间的限制是len = 5):
PUT name_test
{
"settings" : {
"max_ngram_diff": 3,
"analysis":{
"analyzer":{
"2-4nGrams":{
"type":"custom",
"tokenizer":"2-4_ngram_token",
"filter": ["lowercase"]
},
"5-5nGrams":{
"type":"custom",
"tokenizer": "5-5_ngram_token",
"filter": ["lowercase"]
}
},
"tokenizer":{
"2-4_ngram_token": {
"type":"nGram",
"min_gram":"2",
"max_gram":"4"
},
"5-5_ngram_token": {
"type":"nGram",
"min_gram":"5",
"max_gram":"5"
}
}
}
},
"mappings": {
"properties": {
"name": {
"type": "keyword"
},
"name_trans": {
"type": "text",
"fields": {
"2-4partial": {
"type":"text",
"analyzer":"2-4nGrams",
"search_analyzer":"keyword"
},
"5-5partial": {
"type":"text",
"analyzer":"5-5nGrams"
}
}
}
}
}
}
以及根据搜索词的长度与该映射一起使用的两种请求:
GET name_test/_search
{
"query": {
"match": {
"name_trans.2-4partial": {
"query": "ema",
"operator": "and",
"fuzziness": 0
}
}
}
}
GET name_test/_search
{
"query": {
"match": {
"name_trans.5-5partial": {
"query": "emanue",
"operator": "and",
"fuzziness": 0
}
}
}
也许有一天有帮助的人:)
答案 0 :(得分:1)
我不确定在Elasticsearch中是否可行,但是我可以建议您一种变通方法,尽管我们的用例有所不同,但我们也可以在我们的应用程序中使用它。
在要用于部分搜索的字段上使用2-5 ngram tokenzier
创建自定义分析器,这会将字段的ngram标记存储在倒排索引中,例如,包含{ {1}}作为值,它将存储foobar
,fo
,foo
,foob
,fooba
,oo
,{{1 }},oob
,ooba
,oobar
,ob
,oba
,obar
,ba
。
现在,不是匹配查询,而是对未分析的部分字段使用术语查询,因此您可以阅读这些here的diff b / w。
因此,在这种情况下,搜索词是否小于5无关紧要,它仍然会与标记匹配,您将获得结果。
现在,让我们在包含bar
作为值的字段上进行试运行,并针对某些搜索字词对其进行测试,
情况1:如果搜索词包含少于5个字符,例如ar
,foobar
,fo
,oo
,ar
,bar
,oob
和oba
,但它们仍会匹配,因为这些标记存在于倒排索引中。
情况2:搜索词包含等于或大于5个字符,例如bar
,ooba
,然后它还返回文档,因为索引包含这些标记。
请让我知道是否清楚,或者您需要其他说明。