Warm tip: This article is reproduced from serverfault.com, please click

c#-如何使用NEST进行过滤器聚合?

(c# - How to make Filter Aggregations using NEST?)

发布于 2020-11-27 08:51:46

我有使用NEST进行过滤器聚合的要求。但是由于对此我不太了解,所以我做了以下工作:

class Program
{
        static void Main(string[] args)
        {

            ISearchResponse<TestReportModel> searchResponse =
                            ConnectionToES.EsClient()
                            .Search<TestReportModel>
                            (s => s
                                .Index("feedbackdata")
                                .From(0)
                                .Size(50000)
                                .Query(q =>q.MatchAll())
                            );
                            
            var testRecords = searchResponse.Documents.ToList<TestReportModel>();
                
            result = ComputeTrailGap(testRecords);

        }
        
        
        private static List<TestModel> ComputeTrailGap(List<TestReportModel> testRecords)
        {
            var objTestModel = new List<TestModel>();          
            
            var ptpDispositionCodes = new string[] { "PTP" };
            var bptpDispositionCodes = new string[] { "BPTP","SBPTP" };
                  

            int gapResult = testRecords.Where(w => w.trailstatus == "Gap").Count();           

            var ptpResult = testRecords.Where(w => ptpDispositionCodes.Contains(w.lastdispositioncode)).ToList().Count();

            var bptpResult = testRecords.Where(w => bptpDispositionCodes.Contains(w.lastdispositioncode)).ToList().Count();
           

            objTestModel.Add(new TestModel { TrailStatus = "Gap", NoOfAccounts = gapResult });           
            objTestModel.Add(new TestModel { TrailStatus = "PTP", NoOfAccounts = ptpResult });
            objTestModel.Add(new TestModel { TrailStatus = "BPTP", NoOfAccounts = bptpResult });         

            return objTestModel;
        }
}

DTO

public class TestReportModel
{
   
    public string trailstatus { get; set; }        
    public string lastdispositioncode { get; set; }        
}

public class TestOutputAPIModel
{
    public List<TestModel> TestModelDetail { get; set; }    
}

public class TestModel
{   
    public string TrailStatus { get; set; }
    public int NoOfAccounts { get; set; }
    
}

该程序有效,但可以确定我们仅通过NEST访问Elastic Search,其余的Aggregations / Filter则使用Lambda完成。

我想使用NEST框架执行整个操作(聚合/过滤器等),然后使用过滤器聚合将其放入TestModel中。

如何在NEST中构造DSL查询?

更新

到目前为止,我已经能够达到以下要求,但计数为零。我的查询构造有什么问题?

var ptpDispositionCodes = new TermsQuery
            {
                IsVerbatim = true,
                Field = "lastdispositioncode",
                Terms = new string[] { "PTP" },
            };
var bptpDispositionCodes = new TermsQuery
{
    IsVerbatim = true,
    Field = "lastdispositioncode",
    Terms = new string[] { "BPTP" },
};

 ISearchResponse<TestReportModel> searchResponse =
                ConnectionToES.EsClient()
                .Search<TestReportModel>
                (s => s
                    .Index("feedbackdata")
                    .From(0)
                    .Size(50000)
                    .Query(q =>q.MatchAll())
                    .Aggregations(fa => fa

                        .Filter("ptp_aggs", f => f.Filter(fd => ptpDispositionCodes))
                        .Filter("bptp_aggs", f => f.Filter(fd => bptpDispositionCodes))

                        )
               );

结果

在此处输入图片说明

Questioner
priyanka.sarkar
Viewed
0
Sai Gummaluri 2020-11-30 15:16:41

我发现你正在尝试对的类型进行搜索TestReportModel你的方法的总体结构似乎足够好。但是,附加到筛选器容器的查询存在问题。

TestReportModel包含两个属性trialStatuslastdispositioncode你正在将Field属性设置查询内部的描述terms这就是你将计数视为零的原因。你要在其上执行搜索的模型(反过来,你要在其上执行搜索的索引)没有属性description,因此没有区别。NEST或Elasticsearch,在这种情况下不会引发任何异常。而是返回零计数。Field值应修改为lastdispositioncode

// Type on which the search is being performed. 
// Response is of the type ISearchResponse<TestReportModel>
public class TestReportModel
{
    public string trailstatus { get; set; }        
    public string lastdispositioncode { get; set; }        
}

修改后的terms查询如下

// Field is "lastdispositioncode" and not "description"
// You may amend the Terms field as applicable
var ptpDispositionCodes = new TermsQuery
{
    IsVerbatim = true,
    Field = "lastdispositioncode",
    Terms = new string[] { "PTP" },
};

var bptpDispositionCodes = new TermsQuery
{
    IsVerbatim = true,
    Field = "lastdispositioncode",
    Terms = new string[] { "BPTP", "SBPTP" },
};

由于似乎这些值lastdispositioncode似乎取一个单词值(你的示例中为PTP或BPTP),所以我认为,是否对文档中的字段进行分析与否无关紧要。你可以从以下ISearchResponse<T>类型进一步获取计数,如下所示

var ptpDocCount = ((Nest.SingleBucketAggregate)response.Aggregations["ptp_aggs"]).DocCount;
var bptpDocCount = ((Nest.SingleBucketAggregate)response.Aggregations["bptp_aggs"]).DocCount;

编辑:添加关键字搜索方法

QueryContainer qc1 = new QueryContainerDescriptor<TestReportModel>()
    .Bool(b => b.Must(m => m.Terms(t => t.Field(f => f.lastdispositioncode.Suffix("keyword"))
        .Terms(new string[]{"ptp"}))));

QueryContainer qc2 = new QueryContainerDescriptor<TestReportModel>()
    .Bool(b => b.Must(m => m.Terms(t => t.Field(f => f.lastdispositioncode.Suffix("keyword"))
        .Terms(new string[]{"bptp", "sbptp"}))));

现在,可以将这些查询容器挂接到你的聚合中,如下所示

.Aggregations(aggs => aggs
    .Filter("f1", f => f.Filter(f => qc1))
    .Filter("f2", f => f.Filter(f => qc2)))

NEST在这种情况下客户端生成的聚合查询如下所示

"f1": {
      "filter": {
        "bool": {
          "must": [
            {
              "terms": {
                "lastdispositioncode.keyword": [
                  "bptp"
                ]
              }
            }
          ]
        }
      }
    }

同样,回到搜索不区分大小写的情况,Elasticsearch以不区分大小写的方式处理搜索。但是,它取决于已分析字段与未分析字段的不同。默认情况下,对分析字段进行标记化,对文本字段进行标记化。我们理想地在分析场上使用suffix扩展方法,并NEST在分析场上获得精确匹配。在这里更多关于他们的信息