Search code examples
elasticsearchnest

Run elastic search raw query with Nest


I am trying to run a raw query with Nest.Net library on elastic search. The query is as follow:

var json4 = @"
                    {
                      ""query"": {
                        ""bool"": {
                                    ""filter"":{
                                        ""term"":{ ""schoolId"": ""c15677ea-3e1e-4767-936a-2b3c57b00503""}
                                    },
                          ""must"": [
                            {
                              ""multi_match"": {
                                ""query"": ""001 Ali"",
                                ""fields"": [""firstName"",""lastName"", ""phoneNumber"",  ""code"", ""title""],
                                ""type"":  ""cross_fields""
                              }
                    }
                          ]
                        }
                      }
                    }
            ";

        SearchRequest searchRequest;
        using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(json4)))
        {
            searchRequest = client.RequestResponseSerializer.Deserialize<SearchRequest>(stream);
        }

The Deserialize method raise an error as follow:

Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.IEnumerable`1[Nest.QueryContainer]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. Path 'query.bool.filter.term', line 6, position 51.

The query is running in kibana just fine.

Thanks


Solution

  • NEST deserialization supports only the long form of queries i.e.

    • bool query filter clause must be an array of queries; it doesn't support passing an object where the keys of the object are queries
    • term query short form of "term": { "field": "value" } is not supported; it must be of the form "term": { "field" : { "value": "value" } }.

    The following would work

    var json4 = @"
        {
          ""query"": {
            ""bool"": {
              ""filter"":[
                { ""term"":{ ""schoolId"": { ""value"": ""c15677ea-3e1e-4767-936a-2b3c57b00503""}} }
              ],
              ""must"": [
                {
                  ""multi_match"": {
                    ""query"": ""001 Ali"",
                    ""fields"": [""firstName"",""lastName"", ""phoneNumber"",  ""code"", ""title""],
                    ""type"":  ""cross_fields""
                  }
                }
              ]
            }
          }
        }
    ";
    
    SearchRequest searchRequest;
    using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(json4)))
    {
        searchRequest = client.Serializer.Deserialize<SearchRequest>(stream);
    }
    

    BUT, NEST is capable of accepting a query as a JSON string and returning a strongly typed search response using the low level client exposed as the .LowLevel property. With this, there's no need to deserialize the JSON string into a SearchRequest, only to serialize back to JSON when submitting the request. Additionally, you can use the original query you have

    var json4 = @"
        {
          ""query"": {
            ""bool"": {
              ""filter"": { 
                ""term"":{ ""schoolId"": ""c15677ea-3e1e-4767-936a-2b3c57b00503"" } 
              },
              ""must"": [
                {
                  ""multi_match"": {
                    ""query"": ""001 Ali"",
                    ""fields"": [""firstName"",""lastName"", ""phoneNumber"",  ""code"", ""title""],
                    ""type"":  ""cross_fields""
                  }
                }
              ]
            }
          }
        }
    ";
    
    client.LowLevel.Search<SearchResponse<object>>("index", "type", json4);