Эквивалентный запрос linq вasticsearch.net (NEST) - PullRequest
0 голосов
/ 19 декабря 2018

У меня есть следующий тип документа в эластичном:

public class ProductDto
{
   public Int64 Id { get; set; }

   public String Title{ get; set; }

   public bool Visible { get; set; }

   public IList<ProductSupplierDto> ProductSuppliers { get; set; }
}

public class ProductSupplierDto
{
   public Int64 Id { get; set; }

   public String Title{ get; set; }

   public bool Enabled { get; set; }
}

как написать ниже linq-запрос с библиотекой Nest:

var products = db.products.where(p=>  p.Visible 
                                   && p.ProductSuppliers.Any(ps=>ps.Enabled)
                                 ).ToList();

в библиотеке гнезд у меня есть следующий запрос:

var baseQuery = Query<ProductDto>.Term(qt => qt.Field(f => 
                                      f.Visible).Value(true));

как добавить фильтр productuppliers в baseQuery?

Я использую этот метод для создания индекса:

    private async Task CreateIndexIfItDoesntExist<T>(string index) where T: class
    {
        if (!this.client.IndexExists(index).Exists)
        {
            var indexDescriptor = new CreateIndexDescriptor(index)
                            .Settings(x => x.NumberOfReplicas(0))
                            .Mappings(mappings => mappings
                                .Map<T>(m => m.AutoMap()));

            await this.client.CreateIndexAsync(index, i => indexDescriptor);

       // Max out the result window so you can have pagination for >100 pages
           await this.client.UpdateIndexSettingsAsync(index, ixs => ixs
             .IndexSettings(s => s
                 .Setting("max_result_window", int.MaxValue)));


        }
    }

и вызываю так:

await CreateIndexIfItDoesntExist<ProductDto>("products");

методы для индексных данных:

    private async Task<IndexResult> IndexDocuments<T>(T[] datas, string index) where T:class
    {
        int batchSize = 1000; // magic
        int totalBatches = (int)Math.Ceiling((double)datas.Length / batchSize);

        for (int i = 0; i < totalBatches; i++)
        {
            var response = await this.client.IndexManyAsync(datas.Skip(i * batchSize).Take(batchSize), index);

            if (!response.IsValid)
            {
                return new IndexResult
                {
                    IsValid = false,
                    ErrorReason = response.ServerError?.Error?.Reason,
                    Exception = response.OriginalException
                };
            }
            else
            {
                Debug.WriteLine($"Successfully indexed batch {i + 1}");
            }
        }

        return new IndexResult
        {
            IsValid = true
        };
    }

Ответы [ 2 ]

0 голосов
/ 28 декабря 2018

ProductSupplierDto в ProductSuppliers будет отображаться как тип object с автоматическим сопоставлением, поэтому следующий запрос даст то, что вам нужно

var client = new ElasticClient();

var searchResponse = client.Search<ProductDto>(s => s
    .Query(q => +q
        .Term(f => f.Visible, true) && +q
        .Term(f => f.ProductSuppliers[0].Enabled, true)
    )    
);  

. При этом генерируется следующий запрос

{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "visible": {
              "value": true
            }
          }
        },
        {
          "term": {
            "productSuppliers.enabled": {
              "value": true
            }
          }
        }
      ]
    }
  }
}

Пара точек

  1. В запросе используется перегрузка оператора для запросов , чтобы объединить их вместе и сгенерировать запросы, которые выполняются в контексте фильтра (в данном случае,bool запрос filter предложение).Поскольку документ либо совпадает, либо нет, оценка соответствия для соответствия не требуется вычислять.
  2. f => f.ProductSuppliers[0].Enabled - это выражение для получения пути к полю.Это не означает "получить значение Enabled из первого элемента в ProductSuppliers" , но означает "получить путь к полю Enabled всех элементов в ProductSuppliers собственность ".индексатор в коллекции здесь только , чтобы иметь возможность доступа к свойствам типа ProductSupplierDto.

Вы можете рассмотреть отображение ProductSuppliers какnested введите , чтобы вы могли запрашивать свойства отдельных элементов в коллекции ProductSuppliers.Если ProductSuppliers отображается как тип nested, запрос будет

var searchResponse = client.Search<ProductDto>(s => s
    .Query(q => +q
        .Term(f => f.Visible, true) && +q
        .Nested(n => n
            .Path(p => p.ProductSuppliers)
            .Query(nq => nq
                .Term(f => f.ProductSuppliers[0].Enabled, true)
            )
        )           
    )    
);
0 голосов
/ 25 декабря 2018

Как то так?

  QueryContainer baseQuery = Query<ProductDto>.Term(qt => qt.Field(f =>
                                   f.Visible).Value(true));
        baseQuery &= Query<ProductDto>.Term(qt => qt.Field(o => o.ProductSuppliers.Select(a => a.Enabled)).Value(true));

        client.Search<ProductDto>(o => o
           .From(0)
           .Size(10)
           .Query(a => baseQuery));
...