66

需要在 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 值的文档更相关。这只是一个起点——在确定搜索中每个文档的最终相关性分数时,还将考虑查询与其他字段之间的匹配。但是,在其他条件相同的情况下,提升字段越高,文档越相关

任何人都知道如何做到这一点?

非常感谢!

4

4 回答 4

72

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

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

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

最好的解决方案是使用自定义分数查询,它允许您使用脚本进行查询并自定义其分数。相当强大,使用脚本可以直接修改乐谱本身。首先,例如,我会将 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)。

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

于 2012-09-14T19:17:07.500 回答
13

使用最新版本的 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" } }
于 2014-12-14T19:36:31.407 回答
3

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

因此,您的映射可能如下所示:

{
    "_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,}
        }
}
于 2014-01-26T17:23:37.670 回答
0

如果您使用的是 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)
))))
于 2019-09-19T13:39:27.050 回答