首页 > 解决方案 > C# Nest Elasticsearch - 使用上下文描述符按布尔字段过滤完成建议

问题描述

我正在使用完成建议器在用户键入时提供搜索建议。我在我的 C# 类中添加了一个IsActive属性,但我不知道如何在.Suggest.Completion查询中使用它。我知道它与上下文有关,但我找不到弹性搜索/嵌套 6.8 的任何示例。

如何更新我的映射和查询以防止建议带有 IsActive=false 的文档?

这是我的支持类:

[ElasticsearchType(
       IdProperty = "search"
   )]
public class SearchCompletion
{
    public string search { get; set; }


    /// <summary>
    /// Use this field for aggregations and sorts
    /// </summary>
    [Keyword]
    public string search_keyword { get; set; }

    public bool isActive { get; set; }

    /// <summary>
    /// To use for sorting results when searching SearchCompletions 
    /// directly since you can't sort by the Completionfield.Weight 
    /// property for some reason
    /// </summary>
    public int weight { get; set; }

    public CompletionField suggest { get; set; }
}

这是我的映射方法:

public static void MapSearchCompletions(ElasticClient client, string index)
{
    var mapResponse = client.Map<SearchCompletion>(m => m
        .Index(index)
        .AutoMap()


        //  WHAT GOES HERE??
        .Properties(props => props
            .Completion(c => c
                .Name(n => n.isActive)  
                .Contexts(context => context
                    .Category(cat => cat.Name("isActive"))
                )
            )
        )         
    ); //re-apply the index mapping
}

这是我的查询

var response = client.Search<SearchCompletion>(s => s
    .Index(suggest_index)
    .Suggest(su => su
        .Completion("search", cs => cs
            .Field(f => f.suggest)
            .Contexts(con => con.Context("")) //  WHAT GOES HERE??
            .Prefix(search)
            .Size(size)
        )
    )
);

标签: c#elasticsearchnest

解决方案


我认为您不能将boolean其用作category价值。我没有在 ES 中尝试过,但 NEST 接受字符串作为category类型。所以,我建议你更新你的映射。 (我正在更新它以string继续) 看起来您正在其他地方创建索引。您的代码只是创建映射。它可能是:

        var mapResponse = client.Map<SearchCompletion>(m => m
            .Index("index")
            .AutoMap()
            .Properties(props => props
                .Completion(c => c
                    .Name(n => n.suggest)
                    .Contexts(context => context
                        .Category(cat => cat.Name("isActive"))
                    )
                )
            )
        );

        // let's create data
        var r1 = client.Index(new SearchCompletion
        {
            search = "plate", suggest = new CompletionField
            {
                Input = new[] {"plate", "dish"}, // this one has two suggestions
                Contexts = new Dictionary<string, IEnumerable<string>>
                {
                    {
                        "isActive",
                        new[] {"yes"} // isActive is 'yes'
                    }
                }
            }
        }, d => d.Index("index"));

        var r2 = client.Index(new SearchCompletion
        {
            search = "fork",
            suggest = new CompletionField
            {
                Input = new[] { "fork", "dis_example" }, // this has two suggestions
                Contexts = new Dictionary<string, IEnumerable<string>>
                {
                    {
                        "isActive",
                        new[] {"no"} // isActive is 'no'
                    }
                }
            }
        }, d => d.Index("index"));

        var r3 = client.Index(new SearchCompletion
        {
            search = "spoon",
            suggest = new CompletionField
            {
                Input = new[] { "spoon" },
                Contexts = new Dictionary<string, IEnumerable<string>>
                {
                    {
                        "isActive",
                        new[] {"yes"} // isActive is 'yes'
                    }
                }
            }
        }, d => d.Index("index"));

        // Let's search for the dish using 'dis' and limiting it to IsActive == 'yes'
        var searchResponse = client.Search<SearchCompletion>(s => s.Index("index").Suggest(su => su
            .Completion("search", cs => cs
                .Field(f => f.suggest)
                .Contexts(con => con.Context("isActive", aa => aa.Context("yes")))
                .Prefix("dis")
                .Size(10)
            )
        ));

事实上,我们得到了盘子建议:

{
...
  "suggest" : {
    "search" : [
      {
        "text" : "dis",
        "offset" : 0,
        "length" : 3,
        "options" : [
          {
            "text" : "dish",
            "_index" : "testindex",
            "_type" : "searchcompletion",
            "_id" : "plate",
            "_score" : 1.0,
            "_source" : {
              "search" : "plate",
              "weight" : 0,
              "suggest" : {
                "input" : [
                  "plate",
                  "dish"
                ],
                "contexts" : {
                  "isActive" : [
                    "yes"
                  ]
                }
              }
            },
            "contexts" : {
              "isActive" : [
                "yes"
              ]
            }
          }
        ]
      }
    ]
  }
}

推荐阅读