Search code examples
c#elasticsearchnestquerydslelasticsearch.net

MultiMatch ElasticSearch Query with Filter having Must, Must_Not and Should Conditions


I am working on a POC to include Search with ElasticSearch(v7.3) in C# using ElasticSearch.Net and Nest clients. I am trying to build a Json query into Nest Query DSL to get some Data.

Here is the Json Query:

{
    "query": {
    "bool": {
        "must": [
        {
          "multi_match": {
            "query": "human",
            "analyzer": "standard",
            "type": "most_fields",
            "fields": [
              "hasParts.levelProperties.pageTranscript^100",
              "contentTitle^90",
              "documentTitle^80",
              "pageTranscript^70"
            ]
          }
        }
      ],
      "filter": {
        "bool": {
          "must": [
            { "term" : { "documentLevel" : 1 } }
          ],
          "must_not": [
            { "term" : { "moduleNumber" : 4 } } 
          ],
          "should" : [
                {
                    "bool" :{
                        "must" : [
                            { "term" : { "coverDateStartSpecified" : true } },
                            { "term" : { "coverDateEndSpecified" : true } },
                            { 
                                "bool" : {
                                    "should" : [
                                        { "range" : { "coverDateStartYear" : { "gte" : 1946, "lte" : 1975 } } },
                                        { "range" : { "coverDateEndYear" : { "gte" : 1946, "lte" : 1975 } } }
                                    ]
                                }
                            }
                        ]
                    }
                },
                {
                    "bool" :{
                        "must" : [
                            { "range" : { "coverDateYear" : { "gte" : 1946, "lte" : 1975 } } },
                            { 
                                "bool" : {
                                    "should" : [
                                        { "term" : { "coverDateStartSpecified" : false } },
                                        { "term" : { "coverDateEndSpecified" : false } }
                                    ]
                                }
                            }
                        ]
                    }   
                }
            ]
        }
      }
    }
  }
}

This is a very complex query but this is just normal for the Project that I am working on.

I have tried to convert the query:

 var responsedata = _connectionToEs.EsClient().Search<CrSearchContract>(s => s
                                .Size(100).Scroll(1).Query(q => q
                                    .Bool(b => b
                                        .Must(m => m
                                            .MultiMatch(mm => mm
                                                .Query("human")
                                                .Analyzer("standard")
                                                .Type(TextQueryType.MostFields)
                                                .Fields(f => f.Field(ff => ff.DocumentTitle, 80)
                                                    .Field(ff => ff.contentTitle, 90)
                                                    .Field(ff => ff.PageTranscript, 70)
                                                    .Field(ff => ff.PublicationTitle, 60)
                                                    .Field(ff => ff.HasParts[0].LevelProperties.PageTranscript, 100)
                                                )
                                            )
                                        )
                                        .Filter(fil=>fil
                                            .Bool(bl=>bl
                                                .Must(fbm=>fbm.Term(ff=>ff.Field(p=>p.DocumentLevel).Value(1)))
                                                .MustNot(fbmn=>fbmn.Term(ff=>ff.Field(p=>p.ModuleNumber).Value(4)))
                                                .Should(fbs=>fbs
                                                    .Bool(fbsb=>fbsb
                                                        .Must(fbsbm=>fbsbm
                                                            .Term(ff => ff.Field(p => p.CoverDateStartSpecified).Value(true))
                                                        )
                                                    )
                                                )                                                
                                            )
                                        )
                                    )
                                ));

The issue I am facing is with converting the Filter Object of the JSON query to Query DSL. There are multiple Term query in each Must, Must_Not and Should Conditions, which when I try to add in the query gives an error QueryContainer doesn't contain a definition for 'Term' and no..... What am I doing wrong?

Thanks in Advance for the Help!!


Solution

  • You can do this like this

    .Must(
        fbm => fbm.Term(ff => ff.Field(p => p.DocumentLevel).Value(1)), 
        fbm => fbm.Term(ff => ff.Field(p => p.DocumentLevel).Value(2)))
    

    but there are also a couple of other ways of writing bool queries in NEST. It's worth checking docs.

    UPDATE

    You can handle range query with following

    .Range(r => r.Field(f => f.CoverDateStartYear).GreaterThanOrEquals(1946).LessThanOrEquals(1975))
    

    Hope that helps.