【问题标题】:Elasticsearch suggestions with filter带有过滤器的 Elasticsearch 建议
【发布时间】:2016-07-27 20:06:25
【问题描述】:

我需要提供可以正常工作的建议,但我还需要按文档中的另一个字段过滤建议。

这有可能实现吗?只要我想通了,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())));

【问题讨论】:

    标签: c# elasticsearch nest


    【解决方案1】:

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

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

    编辑:

    这是使用 Context Suggester 的完整示例

    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" 的上下文

    【讨论】:

      【解决方案2】:

      您应该使用context suggester 而不是完成建议器,其目标是允许您为完成建议器指定其他类别或地理位置上下文。

      如果我没记错的话,NEST 通过Context 属性将上下文建议器作为完成建议器的一部分提供。

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

      您还需要更改映射中的完成字段以声明上下文。

      【讨论】:

      • 这个运气好吗?
      • 恐怕没有,现在我一点建议都没有。
      • 您是否将映射更改为 specify the context 并在查询中考虑?
      • 是的,如果您查看更新后的问题并查看其中的 ElasticsearchConfig.cs..its,除非我做错了什么。
      • 您是否已使用新映射擦除索引并重新索引数据?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-11
      • 1970-01-01
      • 1970-01-01
      • 2014-06-16
      • 2015-03-31
      • 1970-01-01
      相关资源
      最近更新 更多