c# - 带过滤器的 Elasticsearch 建议

标签 c# 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;
    }

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

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())));

enter image description here

最佳答案

The Context Suggester 扩展了 Completion Suggester 以在类别或地理位置上提供基本过滤元素。这可能足以满足您的目的。

您可能想采用的另一种方法是使用 Context Suggester 提供“按您输入的搜索”建议,在完成类型映射的有效负载中索引每个文档的 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; }
}

这只会产生一个建议,Component Name 1,基于 projectId 的上下文是 "project_id"

关于c# - 带过滤器的 Elasticsearch 建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38622250/

相关文章:

vb.net - ElasticSearch分析的字段

c# - 将 DataGrid 绑定(bind)到队列显示为空

c# - Elasticsearch.net NEST无法过滤URL

c# - ObjectDisposedException 未处理 : Safe handle has been closed at program end

java - 针对 3 个位置字段的 ElasticSearch 查询?

maven - 如何结合neo4j和elasticsearch

search - 如何将2个过滤器应用于ElasticSearch查询对象?

elasticsearch - 如何找到Elastic NEST查询的总点击数?

c# - .NET MVC4 SimpleMembershipProvider - 覆盖密码加密/存储?

c# - 将 ListView 的高度固定为空白