ElasticSearch 匹配 int 和 string 列表

ElasticSearch match on list of int and string

我是 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;
    }    

我希望从 elastic 返回当前类别的产品,但出于某种原因,它给了我不在 category/in 不同类别中的产品。

您的查询不正确。假设以下 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. A 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"
      }
    }
  ]
}

此查询假设 Product 上的 Variants 映射为 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));