Elastic Search using NEST - Results different in d

2019-09-09 16:55发布

问题:

I'm using NEST for ES in .net

This is how im indexing a doc. (Wrote all the elastic client connections in a different class called Settings)

so on a button click

client = Settings.connection();
          var res1 = new Class1
            {
                Id = 1,
                Ans = "The quick brown fox jumps over the lazy dog"
            };
    if (client.IndexExists("zzz").Exists == true)
            {
                client.Index(res1);
            }

string ans = getInfo();

process(ans);

    public string getInfo(){
        string wordInfoQuery = @"{
                        ""query"": {
                            ""match_phrase"":{
                                ""Answer"":{
                                              ""query"": ""brown dog"",
                                              ""slop"": "3"
                                            }
                                        }
                                    }
                                }";


              try
                        {

                            if (client != null)
                            {
                                var callResult = client.LowLevel.Search<string>(wordInfoQuery);
                                reply = callResult.Body.ToString();
                                e.Write(callResult.Body);
                            }

                        }
                               return reply;
    }

public void process(string answer)
        {

            if (!string.IsNullOrEmpty(answer))
            {
                byte[] byteArray = Encoding.UTF8.GetBytes(answer);
                MemoryStream m = new MemoryStream(byteArray);
                float score;
                using (StreamReader r = new StreamReader(m))
                {
                    string json1 = r.ReadToEnd();
                    JObject jobj1 = JObject.Parse(json1);
                    JToken agg1 = jobj1.GetValue("hits")["max_score"];
                    if (agg1!=null) //getting an error here most of the times. if the max_score field is null (for eg: instead of brown dog if i send "tax" as a query term)
                    {
                        score = agg1.ToObject<float>();
                    }
                    else
                    {
                        score = 0;
                    }

                }

            }

        }

class Settings{
public static ElasticClient connection()
        {
            configvalue1 = ConfigurationManager.AppSettings["url"];//stored the url in web.config (http://localhost:9200)

            node = new Uri(configvalue1);
            settings = new ConnectionSettings(node)
                .DefaultIndex("zzz")
                .MapDefaultTypeNames(m => m.Add(typeof(Class1), "omg"));
            client = new ElasticClient(settings);

            if (client.IndexExists("zzz").Exists)
            {
                client.DeleteIndex("zzz"); //i want to index only one doc at a time. so deleting and creating everytime i click on the button
                client.CreateIndex("zzz");
            }


            return client;
        }
    }

In the above code, when i run the code in debug mode, I'm getting a successful post message with query result(for eg. max_Score = 0.28) where as if i run the code in browser mode, it is still making a call to ES , but the result is empty(max_score =""). I dont know why is this happening. someone please help in solving this.

thanks in advance

回答1:

A few observations:

  1. You use "Answer" as the field name for the match_phrase query in your json but NEST by default will camel case all CLR property names when mapping, indexing, searching, etc. This should be "answer" or change the default field name inference on Connection Settings
  2. When there are no results for a match_phrase query, max_score will be null so you will need to handle this case. In your example, a slop of 3 produces no hits for the query so max_score is null. If you change slop to 5, you get the document back and a value for max_score.
  3. I'd recommend using the Fluent API or the Object Initializer Syntax in NEST unless you have good reason not to (and if you do have a reason, we'd love to know!). There are usage examples of all of the Query DSL for NEST 2.x that should hopefully help :)

An example

void Main()
{
    var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
    var defaultIndex = "zzz";

    var connectionSettings = new ConnectionSettings(pool)
            .DefaultIndex(defaultIndex)
            .MapDefaultTypeNames(m => m.Add(typeof(Class1), "omg"))
            .PrettyJson()
            .DisableDirectStreaming()
            .OnRequestCompleted(response =>
                {
                    // log out the request
                    if (response.RequestBodyInBytes != null)
                    {
                        Console.WriteLine(
                            $"{response.HttpMethod} {response.Uri} \n" +
                            $"{Encoding.UTF8.GetString(response.RequestBodyInBytes)}");
                    }
                    else
                    {
                        Console.WriteLine($"{response.HttpMethod} {response.Uri}");
                    }

                    // log out the response
                    if (response.ResponseBodyInBytes != null)
                    {
                        Console.WriteLine($"Status: {response.HttpStatusCode}\n" +
                                 $"{Encoding.UTF8.GetString(response.ResponseBodyInBytes)}\n" +
                                 $"{new string('-', 30)}\n");
                    }
                    else
                    {
                        Console.WriteLine($"Status: {response.HttpStatusCode}\n" +
                                 $"{new string('-', 30)}\n");
                    }
                });

    var client = new ElasticClient(connectionSettings);

    if (client.IndexExists(defaultIndex).Exists)
    {
        client.DeleteIndex(defaultIndex);
    }

    client.CreateIndex(defaultIndex);

    client.Index(new Class1
    {
        Id = 1,
        Answer = "The quick brown fox jumps over the lazy dog"
    }, i => i.Refresh());

    var searchResponse = client.Search<Class1>(s => s
        .Query(q => q
            .MatchPhrase(mp => mp
                .Field(f => f.Answer)
                .Query("brown dog")
                .Slop(5)
            )
        )
    );

    Console.WriteLine(searchResponse.MaxScore);
}

public class Class1
{
    public int Id { get; set; }
    public string Answer { get; set;}
}

Writes out the following to the console

HEAD http://localhost:9200/zzz?pretty=true
Status: 200

------------------------------

DELETE http://localhost:9200/zzz?pretty=true
Status: 200
{
  "acknowledged" : true
}

------------------------------

PUT http://localhost:9200/zzz?pretty=true 
{}
Status: 200
{
  "acknowledged" : true
}

------------------------------

PUT http://localhost:9200/zzz/omg/1?pretty=true&refresh=true 
{
  "id": 1,
  "answer": "The quick brown fox jumps over the lazy dog"
}
Status: 201
{
  "_index" : "zzz",
  "_type" : "omg",
  "_id" : "1",
  "_version" : 1,
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "created" : true
}

------------------------------

POST http://localhost:9200/zzz/omg/_search?pretty=true 
{
  "query": {
    "match": {
      "answer": {
        "type": "phrase",
        "query": "brown dog",
        "slop": 5
      }
    }
  }
}
Status: 200
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 0.07829509,
    "hits" : [ {
      "_index" : "zzz",
      "_type" : "omg",
      "_id" : "1",
      "_score" : 0.07829509,
      "_source" : {
        "id" : 1,
        "answer" : "The quick brown fox jumps over the lazy dog"
      }
    } ]
  }
}

------------------------------

0.07829509