有关嵌套项的elasticsearch multimatch

时间:2018-06-05 14:50:42

标签: c# elasticsearch nest elasticsearch.net

我从客户端获取一个字符串。此字符串可以匹配我的组中的一个字符串,也可以匹配其中一个下层项目的字符串之一。 该字符串是必须查询的。

我让multimatch适用于嵌套查询容器和普通查询容器。我的问题是:如何在单个多匹配中同时获得嵌套层和顶层?

queryList.Add(q => q
            .MultiMatch(mm => mm
                .Fields(fs => fs
                    .Field(f => f.ExtraText)
                    .Field(f => f.SomeText)
                    .Field(f => f.MoreInfo)
                    .Field(f => f.SEOText)
                    .Field(f => f.Title))
                .Query(filter.SearchString)));
queryList.Add(q => q
            .Nested(c => c
                .Path(p => p.Items)
                .Query(nq => nq
                    .MultiMatch(mm => mm
                        .Fields(fs => fs
                            .Field(f => f.Items.First().Subtitle)
                            .Field(f => f.Items.First().Name)
                            .Field(f => f.Items.First().MoreInfo)
                            .Field(f => f.Items.First().ExtraText)
                            .Field(f => f.Items.First().SEOText))
                        .Query(filter.SearchString)))));

扩展: 此搜索查询是对现有数字过滤器的扩展。 在文本搜索旁边还有类别过滤器或组的国家/地区:

if (filter.categories != null && filter.categories.Any())
        {
            foreach (string category in filter.categories)
            {
                queryList.Add(d => d
                    .Nested(nd => nd
                        .Path(np => np.Categories)
                        .Query(nq => nq
                            .Bool(nb => nb
                                .Must(fm => fm
                                    .Match(q => q
                                        .Field(f => f.Categories.First().UrlSlug)
                                        .Query(category)))))));
            }
        }
 if (!string.IsNullOrEmpty(filter.country))
        {
            queryList.Add(d => d.Term(p => p.country, filter.country));
        }

然后将此查询列表提供给搜索:

 _elasticClient.Search<ProductModel>(d => d
                        .Index(_config.GroupIndexName)
                            .Query(q => q
                                .Bool(b => b.Must(queryList))
                            )
                            .Sort(s => s
                                .Field(f => f
                                    .Field(GetSortField(filter.SortOption))
                                    .Order(filter.SortOrder)
                                )
                            )
                            .Skip((filter.Page - 1) * filter.RecordsPerPage)
                            .Take(filter.RecordsPerPage)
                        );

我需要的是searchstring的过滤器是1个单一查询。因此,必须&#39;他们不会互相取消的等级。 (如果字符串与组匹配但不匹配其基础项之一,则均未显示)。

1 个答案:

答案 0 :(得分:0)

Use a bool query。看起来您可能希望将它们组合为should子句,即匹配一个另一个查询

client.Search<MyDocument>(s => s
    .Query(q => q
        .Bool(b => b
            .Should(sh => sh
                .MultiMatch(mm => mm
                    .Fields(fs => fs
                        .Field(f => f.ExtraText)
                        .Field(f => f.SomeText)
                        .Field(f => f.MoreInfo)
                        .Field(f => f.SEOText)
                        .Field(f => f.Title)
                    )
                    .Query(filter.SearchString)
                ), sh => sh
                .Nested(c => c
                    .Path(p => p.Items)
                    .Query(nq => nq
                        .MultiMatch(mm => mm
                            .Fields(fs => fs
                                .Field(f => f.Items.First().Subtitle)
                                .Field(f => f.Items.First().Name)
                                .Field(f => f.Items.First().MoreInfo)
                                .Field(f => f.Items.First().ExtraText)
                                .Field(f => f.Items.First().SEOText))
                            .Query(filter.SearchString)
                        )
                    )
                )
            )
        )
    )
);

可以更简洁地表达

client.Search<MyDocument>(s => s
    .Query(q => q
        .MultiMatch(mm => mm
            .Fields(fs => fs
                .Field(f => f.ExtraText)
                .Field(f => f.SomeText)
                .Field(f => f.MoreInfo)
                .Field(f => f.SEOText)
                .Field(f => f.Title)
            )
            .Query(filter.SearchString)
        ) || q
        .Nested(c => c
            .Path(p => p.Items)
            .Query(nq => nq
                .MultiMatch(mm => mm
                    .Fields(fs => fs
                        .Field(f => f.Items.First().Subtitle)
                        .Field(f => f.Items.First().Name)
                        .Field(f => f.Items.First().MoreInfo)
                        .Field(f => f.Items.First().ExtraText)
                        .Field(f => f.Items.First().SEOText))
                    .Query(filter.SearchString)
                )
            )
        )
    )
);