gpt4 book ai didi

elasticsearch - 如果字段以术语开头,则提高分数

转载 作者:行者123 更新时间:2023-12-03 00:24:40 25 4
gpt4 key购买 nike

我正在尝试在我的网站上进行高效的自动完成搜索输入,以搜索城市。我认为人们将总是开始以正确的词序搜索他们的城市名称。
例如。居住在Saint-Maur中的用户将键入sai..,但绝不会首先键入mau..

如果结果以查询中的字词开头,则需要提高结果的分数。例如。如果用户键入pari,则城市Parigné-le-Pôlin的得分应比Fontenay-en-Parisis更好,因为它以pari开头。

我正在使用边缘语法过滤器和短语匹配,因为单词的顺序很重要。我确定我的问题有一个简单的解决方案,但是我是ES魔术界的新手:)

这是我的映射:

{
"settings": {
"index": {
"number_of_shards": 1
},

"analysis": {
"analyzer": {
"partialPostalCodeAnalyzer": {
"tokenizer": "standard",
"filter": ["partialFilter"]
},
"partialNameAnalyzer": {
"tokenizer": "standard",
"filter": ["asciifolding", "lowercase", "word_delimiter", "partialFilter"]
},
"searchAnalyzer": {
"tokenizer": "standard",
"filter": ["asciifolding", "lowercase", "word_delimiter"]
}
},

"filter": {
"partialFilter": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 50
}
}
}
},

"mappings": {
"village": {
"properties": {
"postalCode": {
"type": "string",
"index_analyzer": "partialPostalCodeAnalyzer",
"search_analyzer": "searchAnalyzer"
},

"name": {
"type": "string",
"index_analyzer": "partialNameAnalyzer",
"search_analyzer": "searchAnalyzer"
},

"population": {
"type": "integer",
"index": "not_analyzed"
}
}
}
}
}

一些样本:
PUT /tv_village/village/1 {"name": "Paris"}
PUT /tv_village/village/2 {"name": "Parigny"}
PUT /tv_village/village/3 {"name": "Fontenay-en-Parisis"}
PUT /tv_village/village/4 {"name": "Parigné-le-Pôlin"}

如果执行此查询,您会看到结果与我想要的顺序不一样(我希望第4个结果在3d之前):
GET /tv_village/village/_search
{
"query": {
"match_phrase": {
"name": "pari"
}
}
}

结果:
      "hits": [
{
"_index": "tv_village",
"_type": "village",
"_id": "1",
"_score": 0.7768564,
"_source": {
"name": "Paris"
}
},
{
"_index": "tv_village",
"_type": "village",
"_id": "2",
"_score": 0.7768564,
"_source": {
"name": "Parigny"
}
},
{
"_index": "tv_village",
"_type": "village",
"_id": "3",
"_score": 0.3884282,
"_source": {
"name": "Fontenay-en-Parisis"
}
},
{
"_index": "tv_village",
"_type": "village",
"_id": "4",
"_score": 0.3884282,
"_source": {
"name": "Parigné-le-Pôlin"
}
}
]

最佳答案

在您的映射定义中,放置另一个分析器:

            "keywordLowercaseAnalyer": {
"tokenizer": "keyword",
"filter": ["lowercase"]
}

意思是,保持单词完整(通过 keyword分析器),并将其小写(例如“parigné-le-pôlin”)。
然后为 name字段定义另外两个字段:
  • 应该是raw的一个not_analyzed
  • 应该使用raw_lowercase的一种keywordLowercaseAnalyer
    "name": {
    "type": "string",
    "index_analyzer": "partialNameAnalyzer",
    "search_analyzer": "searchAnalyzer",
    "fields": {
    "raw": {
    "type": "string",
    "index": "not_analyzed"
    },
    "raw_lowercase": {
    "type": "string",
    "analyzer": "keywordLowercaseAnalyer"
    }
    }
    }

  • 我这样做是因为您可以搜索“pari”或“Pari”。在您的查询中,使用 rescore功能根据其他查询重新计算得分:
    {
    "query": {
    "match_phrase": {
    "name": "pari"
    }
    },
    "rescore": {
    "query": {
    "rescore_query": {
    "bool": {
    "should": [
    {"prefix": {"name.raw": "pari"}},
    {"prefix": {"name.raw_lowercase": "pari"}}
    ]
    }
    }
    }
    }
    }

    从用例 Angular 和关于 prefix查询有两个缺点:
  • 这是相当耗费资源的
  • 传递给prefix的值是not_analyzed,这就是添加这两个raw*字段的原因:一个字段处理小写版本,另一个字段处理未修改的版本,以便查询“pari”或“Pari”涵盖这些情况。

  • 我有两个建议:
  • 在实际数据上测试上面的查询,以查看其行为,性能明智
  • window_size查询一起使用rescore属性,以限制执行计分的值的数量,从而提高性能。

  • 供您引用,这是 documentation page for rescore

    关于elasticsearch - 如果字段以术语开头,则提高分数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26998361/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com