简体   繁体   中英

Dynamic Elastic search query in c# NEST

Started working on NEST api for elastic search recently, got stuck on following query, the data.e would be dynamically populated using the input from client in the HttpGet, ex: user sends eventA,eventB,eventC then we would add in the should part:

GET events/_search
{
  "_source": false, 
  "query": {
    "bool": {
      "must": [
        {"range": {
          "timestamp": {
            "gte": 1604684158527,
            "lte": 1604684958731
            }
        }},
        {"nested": {
          "path": "data",
          "query": {
            "bool": {
              "should": [
                {"match": {
                   "data.e": "eventA"
                }},
                {"match": {
                  "data.e": "eventB"
                }},
                {"match": {
                   "data.e": "eventC"
                }},
              ]
            }
            },
          "inner_hits": {} 
        }}
      ]
    }
  }
}

Following is what I came up with till now:

var graphDataSearch = _esClient.Search<Events>(s => s
                .Source(src => src
                    .Includes(i => i
                        .Field("timestamp")
                        )
                 )
                .Query(q => q
                    .Bool(b => b
                        .Must(m => m
                                .Range(r => r
                                    .Field("timestamp")
                                    .GreaterThanOrEquals(startTime)
                                    .LessThanOrEquals(stopTime)
                                    ),
                                m => m
                                .Nested(n => n
                                    .Path("data")
                                    .Query(q => q
                                        .Bool(bo => bo
                                            .Should(
                                            // what to add here?
                                    )
                                    )
                                )
                        )
                    )
                ));

Can someone please help how to build the should part dynamically based on what input the user sends?

Thanks.

You can replace the nested query in the above snippet as shown below

// You may modify the parameters of this method as per your needs to reflect user input
// Field can be hardcoded as shown here or can be fetched from Event type as below
// m.Field(f => f.Data.e)

public static QueryContainer Blah(params string[] param)
{
    return new QueryContainerDescriptor<Events>().Bool(
        b => b.Should(
            s => s.Match(m => m.Field("field1").Query(param[0])),
            s => s.Match(m => m.Field("field2").Query(param[1])),
            s => s.Match(m => m.Field("field3").Query(param[2]))));
}

What we are essentially doing here is we are returning a QueryContainer object that will be passed to the nested query

.Query(q => Blah(<your parameters>))

The same can be done by adding this inline without a separate method. You may choose which ever route you perfer. However, in general, having a method of its own increases the readability and keeps things cleaner.

You can read more about Match usage here

Edit:

Since you want to dynamically add the match queries inside this, below is a way you can do it.

private static QueryContainer[] InnerBlah(string field, string[] param)
{
    QueryContainer orQuery = null;
    List<QueryContainer> queryContainerList = new List<QueryContainer>();
    foreach (var item in param)
    {
        orQuery = new MatchQuery() {Field = field, Query = item};
        queryContainerList.Add(orQuery);
    }
    return queryContainerList.ToArray();
}

Now, call this method from inside of the above method as shown below

public static QueryContainer Blah(params string[] param)
{
    return new QueryContainerDescriptor<Events>().Bool(
        b => b.Should(
            InnerBlah("field", param)));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM