ElasticSearch - 根据字段值提升相关性

时间:2012-09-14 15:20:43

标签: search elasticsearch

需要在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 个答案:

答案 0 :(得分:68)

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

使用elasticsearch查询DSL有不同的方法来应用查询时间提升:

如果要对匹配特定查询或过滤器的文档进行特定提升,前三个查询很有用。例如,如果您只想提升上个月发布的文档。你可以在你的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)。

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

答案 1 :(得分: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" } }

答案 2 :(得分:3)

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

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

{
    "_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 :(得分: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)
))))