elasticsearch - 如何在不过滤结果的情况下影响 Elasticsearch 中的结果分数?

标签 elasticsearch nest

我希望附近的工作在搜索结果中排名更高,但每当我尝试根据距离更改分数时,我都会得到零结果。我根本不想按距离过滤职位,只想改变结果的相关程度。

我尝试过:

        var response = await client.SearchAsync<JobIndex>(x => x
            .Index(nameof(JobIndex).ToLower())
            .Source(sf => sf.Includes(i => i.Fields(fields)))
            .From(query.Skip.GetValueOrDefault(0))
            .Size(query.Take.GetValueOrDefault(25))
            .Query(q =>
                q.Bool(b => b.MustNot(mustNotQueries))
                && q.Bool(b => b.Must(mustQueries))
                && q.Bool(b => b.Should(shouldQueries))
                && q.FunctionScore(c => c
                    .Query(s => s.MatchAll())
                    .Functions(scoreFunctions)
                )
              ), cancellationToken);

还有:

        var response = await client.SearchAsync<JobIndex>(x => x
            .Index(nameof(JobIndex).ToLower())
            .Source(sf => sf.Includes(i => i.Fields(fields)))
            .From(query.Skip.GetValueOrDefault(0))
            .Size(query.Take.GetValueOrDefault(25))
            .Query(q =>
                q.Bool(b => b.MustNot(mustNotQueries))
                && q.Bool(b => b.Must(mustQueries))
                && q.Bool(b => b.Should(shouldQueries))
              )
            .Query(q => q.FunctionScore(c => c
               .Query(s => s.MatchAll())
               .Functions(scoreFunctions)
            ))
            , cancellationToken);

但我什么也没得到。如果我删除使用“scoreFunctions”的部分,查询工作正常。这是我正在使用的评分函数:

scoreFunctions.Add(new LinearGeoDecayFunction
    {
        Origin = new GeoLocation(result.Latitiude, result.Longitude),
        Field = Infer.Field<JobIndex>(g => g.LatLong),
        Scale = Distance.Miles(50),
        Decay = 0.5
    });

如何编写此查询?

最佳答案

您应该将主查询移至函数分数查询并设置 boost mode到总和,因为您想添加额外的“点”以接近原点。

这是示例应用程序。使用elasticsearch 7.4.0和NEST 7.3.1进行测试

    static async Task Main(string[] args)
    {
        var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
        var connectionSettings = new ConnectionSettings(pool);
        connectionSettings
            .DefaultIndex("documents")
            //do not use in production
            .PrettyJson()
            .DisableDirectStreaming();

        var client = new ElasticClient(connectionSettings);

        await client.Indices.DeleteAsync("documents");

        await client.Indices.CreateAsync("documents", 
            d => d.Map(m => m.AutoMap<City>()));

        await client.IndexManyAsync(new List<City>
        {
            new City
            {
                Id = "1", Name = "Warszawa", Country = "Poland", Location = new GeoLocation(52.237049, 21.017532)
            },
            new City
            {
                Id = "2", Name = "Kraków", Country = "Poland", Location = new GeoLocation(50.049683, 19.944544)
            },
            new City
            {
                Id = "3", Name = "Wieliczka", Country = "Poland", Location = new GeoLocation(49.987061, 20.064796)
            },
            new City
            {
                Id = "4", Name = "Berlin", Country = "Germany", Location = new GeoLocation(52.520008, 13.404954)
            }
        });

        await client.Indices.RefreshAsync();

        var searchResponse = await client.SearchAsync<City>(s => s
            .Query(q => q.FunctionScore(fs =>
                fs
                    .Query(qq =>
                        qq.Match(mm => mm.Field(f => f.Country).Query("Poland")))
                    .BoostMode(FunctionBoostMode.Sum)
                    .Functions(new[]
                    {
                        new LinearGeoDecayFunction
                        {
                            Origin = new GeoLocation(
                                50.049683, 19.944544),
                            Field = Field<City>(
                                f => f.Location),
                            Scale = Distance.Kilometers(100),
                            Decay = 0.5
                        }
                    }))));

        foreach (var hit in searchResponse.Hits)
        {
            System.Console.WriteLine($"Name: {hit.Source.Name} Score: {hit.Score}");
        }
    }

    public class City
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public string Country { get; set; }
        [GeoPoint]
        public GeoLocation Location { get; set; }
    }
}

输出

Name: Kraków Score: 1.3566749
Name: Wieliczka Score: 1.3013793
Name: Warszawa Score: 0.35667494

希望有帮助。

关于elasticsearch - 如何在不过滤结果的情况下影响 Elasticsearch 中的结果分数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58562236/

相关文章:

elasticsearch - Nest中的ElasticSearch多重匹配

docker - 无法使用docker在Apple Mac芯片M1上启动elasticsearch

ruby - 如何在Elasticsearch中优先考虑整个单词?

elasticsearch - NEST查询未返回Elasticsearch中保存的Metricbeat字段的数据

elasticsearch - 使用弹性聚合(NEST)时为null_pointer_exception

c# - Netcore Elasticsearch(NEST)默认索引为UriEncoded

Elasticsearch Map 对 not_analyzed 文档不区分大小写

elasticsearch - 当Content-type:application/json存在时,Hapijs避免JSON验证

amazon-web-services - Elasticsearch 语音分析器返回零结果?

nest - 使用 Elasticsearch 客户端发布原始 json