使用.Net NEST客户端为产品目录创建Elasticsearch查询

时间:2017-08-23 11:12:08

标签: c# nest elasticsearch-5 elasticsearch-net elasticsearch-nested

使用.NET的Elasticsearch NEST库我正在尝试创建一个搜索产品的查询。该模型的结构如下:

[ElasticsearchType(Name = "product", IdProperty = "ProductId")]
public class ProductIndex
{
    [Number(NumberType.Integer)]
    public int ProductId { get; set; }

    [Text]
    public string Name { get; set; }

    [Text]
    public string Description { get; set; }

    [Number(NumberType.Integer)]
    public int BranchId { get; set; }

    [Number(NumberType.Integer)]
    public int SubbranchId { get; set; }

    [Number(NumberType.Float)]
    public decimal Rating { get; set; }

    [Boolean]
    public bool IsActive { get; set; }

    [Date]
    public DateTime PublishedAt { get; set; }

    [Nested]
    public ICollection<VariantIndex> Variants { get; set; }
}

[ElasticsearchType(Name = "variant", IdProperty = "VariantId")]
public class VariantIndex
{
    public int VariantId { get; set; }
    public decimal Price { get; set; }
    public IEnumerable<string> Values { get; set; }
}

我需要根据以下参数过滤产品:

  • branchId(int):产品BranchId等于branchId 参数,
  • subbranches(int []):产品SubbranchId包含在 subbranches array
  • rating(int):产品评级大于或等于 评级参数
  • minPrice(int):产品变体价格大于minPrice 参数
  • maxPrice(int):产品变体价格低于maxPrice 参数
  • searchTerm(string):产品名称或描述包含字符串searchTerm
  • tags(string []):产品变体值包含一个或多个或 所有标签。

注: branchId 子分支 评分 < / strong>和 searchTerm 应过滤掉顶级的ProductIndex对象。然后, minPrice maxPrice 参数应过滤掉任何嵌套的Variants对象,如果它们的价格不在指定的位置范围,最后 标记 参数应过滤掉任何不包含其Values数组中任何标记的嵌套Variants对象,或根据标记的数量对其进行适当评分。在数组数组中匹配。

最终结果应该是已评分的ProductIndex对象列表,每个对象都包含已筛选和评分的VariantIndex对象的列表。

以下是我尝试创建查询的方法,但这给了我完全错误的搜索结果:

Func<SearchDescriptor<ProductIndex>, ISearchRequest> search = s => s
            .From(page * 10)
            .Size(10)
            .Query(q => q
                .Bool(b => b
                    .Must(mu => mu
                        .Match(m => m
                            .Field(f => f.Name)
                            .Query(searchTerm)
                        ), mu => mu
                        .Match(m => m
                            .Field(f => f.Description)
                            .Query(product)
                        ), mu => mu
                        .Terms(t => t
                            .Field(f => f.Variants.Select(v => v.Values))
                            .Terms(tags)
                        )
                    )
                    .Filter(bf => bf
                        .Term(t => t
                        .Field(p => p.BranchId)
                        .Value(mainbranch))
                     )
                    .Filter(bf => bf
                            .Terms(t => t
                            .Field(p => p.SubbranchId)
                            .Terms(subbranches)
                        )
                    )
                    .Filter(bf => bf
                        .Range(r => r
                            .Field(f => f.Variants.Select(v => v.Price))
                            .GreaterThanOrEquals(minPrice)
                            .LessThanOrEquals(maxPrice)
                        )
                    )
                )
            );


        var response = await client.SearchAsync<ProductIndex>(search);

编辑1: 基于我自己的调查评论,我终于设法创建一个正常的查询。剩下要做的唯一事情就是过滤掉嵌套的VariantIndex对象列表,这样我们才能获得符合 价格 标签的变体 过滤器。 我应该在查询的最新工作版本中添加哪些代码才能实现此目的?

Func<SearchDescriptor<ProductIndex>, ISearchRequest> search = s => s.Type<ProductIndex>()
            .Query(q => q
                .Bool(b => b
                    .Must(m => m
                        .MultiMatch(mm => mm
                            .Query(product)
                            .Fields(f =>
                                f.Fields(f1 => f1.Name, f2 => f2.Description)
                            )
                        )
                    )
                    .Should(ss => ss
                        .Match(m => m
                            .Field(f => f.Variants.Select(v => v.Values))
                            .Query(tagsJoined)
                        )
                    )
                    .Filter(m => m
                        .Bool(bl => bl
                            .Must(ms => ms
                                .Range(r => r
                                    .Field(f => f.Rating)
                                    .GreaterThanOrEquals(rating)
                                ),
                                ms => ms
                                    .Range(r => r
                                        .Field(f => f.Variants.Select(v => v.Price))
                                        .GreaterThanOrEquals(minPrice)
                                        .LessThanOrEquals(maxPrice)
                                    )
                            )
                        )

                    )
                )

            )

0 个答案:

没有答案