【问题标题】:Equivalent linq query in elasticsearch.net(NEST)elasticsearch.net(NEST)中的等效 linq 查询
【发布时间】:2018-12-19 15:28:36
【问题描述】:

我在弹性中有以下文档类型:

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

如何使用 Nest libray 编写以下 linq 查询:

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

如何在 baseQuery 中添加 productsuppliers 过滤器?

我用这个方法来创建索引:

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

【问题讨论】:

  • 请您也提供ProductDto的索引映射,因为它需要正确回答
  • @RussCam 我的问题已更新。
  • 感谢@Iraj - 只需要索引中存在的映射 JSON,但提供的代码表明

标签: c# .net linq elasticsearch nest


【解决方案1】:

ProductSuppliers 中的ProductSupplierDto 将被映射为具有自动映射的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. 查询使用operator overloading on queries 将它们组合在一起并生成在过滤上下文中执行的查询(在本例中为bool 查询filter 子句)。由于文档要么匹配要么不匹配,因此无需计算匹配的相关性分数。
  2. f =&gt; f.ProductSuppliers[0].Enabled 是获取字段路径的表达式。不是说“从ProductSuppliers中的第一项获取Enabled的值”,而是说“获取@中所有项目的Enabled字段的路径987654334@ 财产”。此处集合中的索引器仅能够访问ProductSupplierDto 类型的属性。

您可能需要consider mapping ProductSuppliers as a nested type,以便能够查询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)
            )
        )           
    )    
);

【讨论】:

    【解决方案2】:

    这样的?

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

    【讨论】:

    • 问题不是答案。一个最小的答案提供了一个解决方案(最好是代码)和基本部分的简要说明。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-01
    • 1970-01-01
    • 2021-04-27
    • 2012-08-23
    相关资源
    最近更新 更多