代码之家  ›  专栏  ›  技术社区  ›  Jannik

int和string列表上的ElasticSearch匹配

  •  0
  • Jannik  · 技术社区  · 6 年前

    我对ElasticSearch还比较陌生,我正试图查询我们的分类页面,其中ES返回的每个产品都在分类中。出于某种原因,它包含了这个类别之外的产品,我似乎不知道为什么。

    产品是一个基本产品,包含一个类别ID列表(产品可以在多个类别中)。除了匹配CategoryID之外,还应该在产品名称和变体的详细描述中进行搜索。

    public IReadOnlyCollection<Product> GetByCategory(string value, int take, int categoryId)
        {
            value = string.Format("*{0}*", value);
    
            var query = new SearchDescriptor<Product>()
                .Index(this.index)
                .Query(q => q
                  .Bool(b => b
                    .Must(s => s
                      .Match(m => m
                        .Field(ff => ff
                          .AttachedCategoryIds.Contains(categoryId)
                        )
                      )
                    )
                    .Must(s => s
                      .QueryString(m => m
                        .Query(value)
                          .Fields(ff => ff
                            .Field(f => f.Name)
                            .Field(f => f.Variants.Select(input => input.LongDescription))
                          )
                          .Type(TextQueryType.CrossFields)
                        )
                      )
                    )
                  )
                  .Size(take)
                  .Sort(ss => ss.Descending(SortSpecialField.Score));
    
            var data = client.Search<Product>(query);
    
            var products = data.Documents;
    
            return products;
        }    
    

    我希望从弹性中只得到当前类别的产品,但出于某种原因,它给了我不属于某个类别/不同类别的产品。

    1 回复  |  直到 6 年前
        1
  •  0
  •   Russ Cam    6 年前

    您的查询不正确。假设以下POCO

    public class Product
    {
        public string Name { get; set; }
        public List<Variant> Variants { get; set; }
        public List<int> AttachedCategoryIds { get; set; }
    }
    
    public class Variant
    {
        public string LongDescription { get; set; }
    }
    

    查询应该是

    var index = "index_name";
    var categoryId = 1;
    
    var value = "this is the query";
    var take = 20;
    
    var query = new SearchDescriptor<Product>()
        .Index(index)
        .Query(q => q
            .Bool(b => b
                .Must(s => s
                    .QueryString(m => m
                        .Query(value)
                        .Fields(ff => ff
                            .Field(f => f.Name)
                            .Field(f => f.Variants.First().LongDescription)
                        )
                        .Type(TextQueryType.CrossFields)
                    )
                )
                .Filter(f => f
                    .Term(ff => ff.AttachedCategoryIds, categoryId)
                )
            )
        )
        .Size(take)
        .Sort(ss => ss.Descending(SortSpecialField.Score));
    
    var searchResponse = client.Search<Product>(query);
    

    几点

    1. .Field(f => f.Variants.First().LongDescription) 是一个 表达 这将解析为一个字符串,该字符串将在JSON中序列化,以在ElasticSearch中针对某个字段。在这种情况下,这将解决 "variants.longDescription"

    2. term query 可用于确定ElasticSearch中的字段是否包含特定值。我已将查询放入 bool 查询筛选子句,因为我认为您不想为查询的这一部分计算相关性得分,即文档要么在字段中包含该术语,要么不包含该术语。

    此操作将序列化到以下查询

    POST http://localhost:9200/index_name/product/_search 
    {
      "query": {
        "bool": {
          "filter": [
            {
              "term": {
                "attachedCategoryIds": {
                  "value": 1
                }
              }
            }
          ],
          "must": [
            {
              "query_string": {
                "fields": [
                  "name",
                  "variants.longDescription"
                ],
                "query": "this is the query",
                "type": "cross_fields"
              }
            }
          ]
        }
      },
      "size": 20,
      "sort": [
        {
          "_score": {
            "order": "desc"
          }
        }
      ]
    }
    

    此查询假设 Variants Product 被映射为 object 数据类型。它可以更多 succinctly written 作为

    var query = new SearchDescriptor<Product>()
        .Index(index)
        .Query(q => q
            .QueryString(m => m
                .Query(value)
                .Fields(ff => ff
                    .Field(f => f.Name)
                    .Field(f => f.Variants.First().LongDescription)
                )
                .Type(TextQueryType.CrossFields)
            ) && +q
            .Term(ff => ff.AttachedCategoryIds, categoryId)
        )
        .Size(take)
        .Sort(ss => ss.Descending(SortSpecialField.Score));