Search code examples
c#nest

Search multiple fields query_string return no result - ElasticSearch


I have this DSL query which return result in ElasticSearch console.

GET /person/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "query_string": {
            "fields": [
              "nameDetails.name.nameValue.firstName",
              "nameDetails.name.nameValue.surname",
              "nameDetails.name.nameValue.middleName"
            ],
            "query": "Pibba Fawsu~"
          }
        }
      ]
    }
  }
}

The result is below:

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 10.335077,
    "hits" : [
      {
        "_index" : "person",
        "_type" : "_doc",
        "_id" : "70002",
        "_score" : 10.335077,
        "_source" : {
          "gender" : "Male",
          "nameDetails" : {
            "name" : [
              {
                "nameValue" : {
                  "firstName" : "Fawsu",
                  "middleName" : "L.",
                  "surname" : "Pibba"
                },
                "nameType" : "Primary Name"
              },
              {
                "nameValue" : {
                  "firstName" : "Fausu",
                  "middleName" : "L.",
                  "surname" : "Pibba"
                },
                "nameType" : "Spelling Variation"
              }
            ]
          }          
        }
      }
    ]
  }
}

But when I convert the query to NEST C#, it return no result.

var response = await _elasticClient.SearchAsync<Person>(s => s
  .Index("person")
  .Query(q => q
      .Bool(b => b
          .Must(                      
            mu => mu
          .QueryString(m => m
              .Fields(f => f.Field(f => f.NameDetails.Name[0].NameValue.FirstName))
              .Fields(f => f.Field(f => f.NameDetails.Name[0].NameValue.Surname))
              .Fields(f => f.Field(f => f.NameDetails.Name[0].NameValue.MiddleName))
              .Query("Pibba Fawsu")
          )
       )
      )                  
  )
);

But when I test it with just FirstName like below, it returns result.

var response = await _elasticClient.SearchAsync<Person>(s => s
  .Index("person")
  .Query(q => q
      .Bool(b => b
          .Must(                      
            mu => mu
          .QueryString(m => m
              .Fields(f => f.Field(f => f.NameDetails.Name[0].NameValue.FirstName))
              .Query("Pibba Fawsu")
          )
       )
      )                  
  )
);

Solution

    • Query string query returns documents based on a provided query string, using a parser with a strict syntax. Your first NEST c# code emphasize match all field, but no result. So you should add MinimumShouldMatch restriction.
    • You can add should condition on firstName, surName, middleName. Even if one name had been matched, it would like to return.
    client.Search<Document>(s => s
        .Query(q => q
            .Bool(b => b
                .Should(sh => sh
                    .Match(c => c
                        .Field(p => p.firstName)
                        .Query(keyz)
                    ),
    sh => sh
                    .Match(c => c
                        .Field(p => p.middleName)
                        .Query(keyz)
                    ),
                        sh => sh
                    .Match(c => c
                        .Field(p => p.surName)
                        .Query(keyz)
                    )
                )
            )
        )
    );