ElasticSearch совпадение в списке int и строки - PullRequest
0 голосов
/ 15 января 2019

Я довольно новичок в ElasticSearch и пытаюсь сделать запрос для нашей страницы категории, где каждый продукт, возвращаемый ES, находится в категории. По какой-то причине он включает в себя продукты за пределами категории, и я не могу понять, почему.

Товар - это базовый товар, содержащий список идентификаторов категорий (товар может быть нескольких категорий). Помимо сопоставления по 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 Ответ

0 голосов
/ 15 января 2019

Ваш запрос не верный. Предполагая, что следующие 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"
      }
    }
  ]
}

Этот запрос предполагает, что Variants на Product отображается как тип данных object. Это может быть более кратко написано как

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