带过滤器的Elasticsearch建议

Chi*_*mar 6 elasticsearch nest

我要求提供正常工作的建议,但我还需要通过文档中的其他字段过滤建议.

这有可能实现吗?只要我知道,Elasticsearch就无法做到这一点.还有其他想法吗?

public async Task<ISuggestResponse> Suggest(string index, string projectId, string field, string text)
        {
            var suggestResponse = await _client.SuggestAsync<TDocument>(s => s
                                                                            .Index(index)
                                                                            .Completion("suggest", c => c
                                                                                    .Text(text)
                                                                                    .Context(con => con.Add("projectId", projectId))
                                                                                    .Field(field)
                                                                                    .Size(20)
                                                                                )
                                                                    );

        return suggestResponse;
    }
Run Code Online (Sandbox Code Playgroud)

-----------更新--------------------

ElasticsearchConfig.cs

client.Map<Component>(d => d
        .Properties(props => props
            .String(s => s
                .Name("name"))
            .Completion(c => c
                .Name("componentSuggestion")
                .Analyzer("simple")
                .SearchAnalyzer("simple")
                .Context(context => context
                    .Category("projectId", cat => cat
                    .Field(field => field.ProjectId)))
                .Payloads()))
        .Properties(props => props.String(s => s.Name("id").NotAnalyzed()))
        .Properties(props => props.String(s => s.Name("projectId").NotAnalyzed())));
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

Rus*_*Cam 4

上下文建议器扩展了完成建议器,以提供针对类别或地理位置的基本过滤元素。这可能足以满足您的目的。

您可能想要采用的另一种方法是使用上下文建议器来提供输入时搜索建议,在完成类型映射的有效负载中对​​每个文档的 id 进行索引;然后使用有效负载中返回的 ID 来搜索文档,此时应用附加过滤并仅返回与过滤匹配的文档 ID。最后,使用这些文档 ID 从原始建议响应中获取建议。

编辑:

这是使用上下文建议器的完整示例

void Main()
{
    var componentsIndex = "components";
    var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
    var settings = new ConnectionSettings(connectionPool)
        // use component index when working with
        // Component Poco type
        .InferMappingFor<Component>(m => m
            .IndexName(componentsIndex)
        );

    var client = new ElasticClient(settings);

    // make this example repeatable, so delete index if
    // it already exists
    if (client.IndexExists(componentsIndex).Exists)
        client.DeleteIndex(componentsIndex);

    // for example purposes, only use one shard and no replicas
    // NOT RECOMMENDED FOR PRODUCTION
    client.CreateIndex(componentsIndex, c => c
        .Settings(s => s
            .NumberOfShards(1)
            .NumberOfReplicas(0)
        )
    );

    client.Map<Component>(d => d
        .Index(componentsIndex)
        // infer mapping of fields from property of the POCO.
        // This means we don't need to explicitly specify all 
        // mappings in .Properties()
        .AutoMap()
        // Now, override any inferred mappings from automapping
        .Properties(props => props
            .Completion(c => c
                .Name(n => n.ComponentSuggestion)
                .Context(context => context
                    .Category("projectId", cat => cat
                        .Field(field => field.ProjectId)
                    )
                )
                .Payloads()
            )
            .String(s => s
                .Name(n => n.Id)
                .NotAnalyzed()
            )
            .String(s => s
                .Name(n => n.ProjectId)
                .NotAnalyzed()
            )
        )
    );

    var components = new[] {
        new Component
        {
            Id = "1",
            Name = "Component Name 1",
            ComponentSuggestion = new CompletionField<object>
            {
                Input = new [] { "Component Name 1" },
                Output = "Component Name 1"
            },
            ProjectId = "project_id"
        },
        new Component
        {
            Id = "2",
            Name = "Component Name 2",
            ComponentSuggestion = new CompletionField<object>
            {
                Input = new [] { "Component Name 2" },
                Output = "Component Name 2"
            },
            ProjectId = "project_id_2"
        }
    };

    // index some components with different project ids
    client.IndexMany(components);

    // refresh the index to make the newly indexed documents available for
    // search. Useful for demo purposes but,
    // TRY TO AVOID CALLING REFRESH IN PRODUCTION     
    client.Refresh(componentsIndex);

    var projectId = "project_id";

    var suggestResponse = client.Suggest<Component>(s => s
        .Index(componentsIndex)
        .Completion("suggester", c => c
            .Field(f => f.ComponentSuggestion)
            .Text("Compon")
            .Context(con => con.Add("projectId", projectId))
            .Size(20)
        )
    );

    foreach (var suggestion in suggestResponse.Suggestions["suggester"].SelectMany(s => s.Options))
    {
        Console.WriteLine(suggestion.Text);
    }
}

public class Component
{
    public string Id { get; set; }

    public string Name { get; set; }

    public string ProjectId { get; set; }

    public CompletionField<object> ComponentSuggestion { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这仅产生一个建议,Component Name 1基于projectId存在的上下文"project_id"