ElasticSearch——基于字段值提升相关性

Posted

技术标签:

【中文标题】ElasticSearch——基于字段值提升相关性【英文标题】:ElasticSearch -- boosting relevance based on field value 【发布时间】:2012-09-07 18:59:58 【问题描述】:

需要在 ElasticSearch 中找到一种方法,以根据字段的特定值提高文档的相关性。具体来说,在我的所有文档中都有一个特殊字段,字段值越高,包含它的文档应该越相关,无论搜索如何。

考虑以下文档结构:


    "_all" : "enabled" : "true",
    "properties" : 
        "_id":            "type" : "string",  "store" : "yes", "index" : "not_analyzed",
        "first_name":     "type" : "string",  "store" : "yes", "index" : "yes",
        "last_name":      "type" : "string",  "store" : "yes", "index" : "yes",
        "boosting_field": "type" : "integer", "store" : "yes", "index" : "yes"
        

我希望 boosting_field 值较高的文档比 boosting_field 值较低的文档在本质上更相关。这只是一个起点——在确定搜索中每个文档的最终相关性分数时,还将考虑查询与其他字段之间的匹配。但是,在其他条件相同的情况下,提升字段越高,文档的相关性越高

有人知道怎么做吗?

非常感谢!

【问题讨论】:

另请参阅***.com/a/41813578/5444623,了解按文档类型字段进行的不同提升 【参考方案1】:

您可以在索引时或查询时提升。我通常更喜欢查询时间提升,即使它会使查询变慢一点,否则每次我想更改提升因子时都需要重新索引,这通常需要微调并且需要非常灵活。

使用 elasticsearch 查询 DSL 应用查询时间提升的方法有多种:

Boosting Query Custom Filters Score Query Custom Boost Factor Query Custom Score Query

如果您想对匹配特定查询或过滤器的文档进行特定提升,前三个查询很有用。例如,如果您只想提升上个月发布的文档。您可以将这种方法与您的 boosting_field 一起使用,但您需要手动定义一些 boosting_field 间隔并给它们一个不同的提升,这不是很好。

最好的解决方案是使用Custom Score Query,它允许您使用脚本进行查询并自定义其分数。相当强大,使用脚本可以直接修改乐谱本身。首先,例如,我会将 boosting_field 值缩放为从 0 到 1 的值,这样您的最终分数就不会变成一个大数字。为此,您需要预测该字段可以包含的或多或少的最小值和最大值。例如,假设最小 0 和最大 100000。如果将 boosting_field 值缩放为 0 到 1 之间的数字,则可以将结果添加到实际分数中,如下所示:


    "query" : 
        "custom_score" : 
            "query" : 
                "match_all" : 
            ,
            "script" : "_score + (1 * doc.boosting_field.doubleValue / 100000)"
        
    

您还可以考虑将 boosting_field 用作提升因子(_score * 而不是 _score +),但是您需要将其缩放到最小值为 1 的区间(只需添加 +1)。

您甚至可以调整结果以改变其重要性,为您用来影响分数的值添加权重。如果您需要将多个增强因子组合在一起以赋予它们不同的权重,您将更需要这个。

【讨论】:

你能在custom_score中容纳和过滤吗?现在你的查询只有match_all,你能在里面添加一些过滤吗? 您可以使用 filtered query 并向其添加查询和过滤器。 但这无济于事。您在示例中编写的内容对我来说很好,但需要在主查询中添加一个过滤器。, "filter": "and": [ "query": "match": "xxxx": "query": "barfoo" ] 没错,现在只有一个查询来统治所有这些:function_score 查询。【参考方案2】:

如果您想避免每次在查询中进行提升,您可以考虑将其添加到您的映射中,直接添加“提升:因子”。

所以您的映射可能如下所示:


    "_all" : "enabled" : "true",
    "properties" : 
        "_id":            "type" : "string",  "store" : "yes", "index" : "not_analyzed",
        "first_name":     "type" : "string",  "store" : "yes", "index" : "yes",
        "last_name":      "type" : "string",  "store" : "yes", "index" : "yes",
        "boosting_field": "type" : "integer", "store" : "yes", "index" : "yes", "boost" : 10.0,
        

【讨论】:

将它添加到查询中不仅仅是重复,您可以每次更改查询时间提升,而如果您将提升添加到索引时间提升的映射中,您需要将其重新索引为更改。我总是建议查询时间增加而不是索引时间增加。【参考方案3】:

使用最新版本的 Elasticsearch(1.3+ 版),您需要使用“功能得分查询”:

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html

评分的 query_string 搜索如下所示:


 'query': 
        'function_score': 
            'query':  'query_string':  'query': 'my search terms'  ,
            'functions': [ 'field_value_factor':  'field': 'my_boost'  ]
        
    

“my_boost”是搜索索引中的一个数字字段,其中包含单个文档的提升因子。可能看起来像这样:

 "my_boost":  "type": "float", "index": "not_analyzed"  

【讨论】:

【参考方案4】:

如果您使用的是 Nest,则应使用以下语法:

.Query(q => q
    .Bool(b => b
        .Should(s => s
            .FunctionScore(fs => fs
                .Functions(fn => fn
                    .FieldValueFactor(fvf => fvf
                        .Field(f => f.Significance)
                        .Weight(2)
                        .Missing(1)
        ))))
        .Must(m => m
            .Match(ma => ma
                .Field(f => f.MySearchData)
                    .Query(query)
))))

【讨论】:

以上是关于ElasticSearch——基于字段值提升相关性的主要内容,如果未能解决你的问题,请参考以下文章

Elasticsearch:Rank feature query - 排名功能查询

ElasticSearch实战(四十)-度量值聚合

ElasticSearch实战(四十)-度量值聚合

Elasticsearch聚合优化 | 聚合速度提升5倍!

干货 | Debezium实现Mysql到Elasticsearch高效实时同步

Elasticsearch——评分机制详解