你如何调试你的Nest查询?

时间:2015-01-25 17:59:39

标签: c# elasticsearch nest

我是Nest的新手,我很可能不像我想的那样创建我的查询。我的问题更像是教人钓鱼而不是给我一条鱼。但是,我将以当前问题为例。

我在类型Series的ElasticSearch中有几个文档。我将在下面没有属性和公共修饰符,只包含与查询相关的信息:

class Series
{
    string Id {get; set;}
    DateTime StartDate {get; set;}
    DateTime EndDate {get; set;}
    HashSet<Role> ReleasableTo {get; set;}
}

这些都很精致和花花公子。我可以Get() Series对象没问题。我遇到的问题是试图找出Nest如何格式化我的查询。我的近期目标是找到Series可释放的最新Role.Visitor。我设置了这样的Nest查询:

ISearchResponse<Series> response = client
    .Search<Series>(r => 
         r.Filter(f => 
             f.Term<Role>(t=>t.ReleasableTo.First(), Role.Visitor))
    .SortDescending(ser => ser.EndDate).Size(1));

在我看来,这应该是生成一个过滤系列的查询,因此它只考虑ReleasableTo我的Role.Visitor,按结束日期反向排序,并将结果限制为返回的结果。这正是我想要的。在我为系列制作的数千条记录中,大约90%符合此配置文件。不幸的是,查询返回0结果。没有错误,只是没有结果。我不知道的是,如果我错误地使用API​​,如果Nest生成的查询结构没有意义,或者我根本不了解ElasticSearch。当我删除Filter条款时,我得到了一个结果,但我不能保证每个人都可以看到它。

如何查看Nest生成并发送给ElasticSearch的JSON?

8 个答案:

答案 0 :(得分:13)

您可以获取搜索请求URL和JSON请求正文的值,如下所示:

var requestURL = response.RequestInformation.RequestUrl;
var jsonBody = Encoding.UTF8.GetString(response.RequestInformation.Request);

您可以在RequestInformation中找到其他有用的属性以进行调试。

答案 1 :(得分:7)

我想比bsarkar建议更进一步,并且完全不需要进行往返:

var client = new ElasticClient();

var seriesSearch = new SearchDescriptor<Series>();
seriesSearch.Filter(f => f
    .Term<Role>(t => t.ReleasableTo.First(), Role.Visitor))
    .SortDescending(ser => ser.EndDate)
    .Size(1));

string searchJson = Encoding.UTF8.GetString(client.Serializer.Serialize(seriesSearch));

请注意,您的ElasticClient不需要任何连接属性,因此您不依赖于ES节点。

答案 2 :(得分:7)

NEST是.NET API的巴洛克式。对于2.1+的通话级别:

IElasticClient client = new ElasticClient();
var searchDescriptor = new SearchDescriptor<Series>();
var query = Query<Series>.Term(...);
var pretty = query.ToPrettyString(query);
var json = client.ToRawRequest(searchDescriptor.Query(descriptor => query));

在配置级别:

    var settings = new ConnectionSettings()
                     .PrettyJson().DisableDirectStreaming()
                     .OnRequestCompleted(details=> Debug.WriteLine(Encoding.UTF8.GetString(details.RequestBodyInBytes)));

在响应级别上查看CallDetails.RequestBodyInBytes

使用过的扩展程序:

    /// <summary>
    /// Converts search to raw JSON request for debugging.
    /// </summary>
    /// <typeparam name="T">The type.</typeparam>
    /// <param name="self">The self.</param>
    /// <param name="searchDescriptor">The search descriptor.</param>
    /// <returns>The string.</returns>
    public static string ToRawRequest<T>(this IElasticClient self, SearchDescriptor<T> searchDescriptor) where T : class
    {
        using (var output = new MemoryStream())
        {
            self.Serializer.Serialize(searchDescriptor, output);
            output.Position = 0;
            var rawQuery = new StreamReader(output).ReadToEnd();
            return rawQuery;
        }
    }

    /// <summary>
    /// Prints query into string.
    /// </summary>
    /// <param name="self">The self.</param>
    /// <returns>The value.</returns>
    public static string ToPrettyString(this QueryContainer self)
    {
        using (var settings = new ConnectionSettings())
        {
            var visitor = new DslPrettyPrintVisitor(settings);
            self.Accept(visitor);
            return visitor.PrettyPrint.Replace(Environment.NewLine, string.Empty);
        }                                                                         
    }

答案 3 :(得分:6)

真的很容易。如果这是我的搜索代码:

var results = client.Search<SearchItem>(s => s.AllIndices()
    .Query(q =>
            q.Term(p => p.LastName, searchItem.LastName)
            && q.Term(p => p.FirstName, searchItem.FirstName)
            && q.Term(p => p.ApplicationCode, searchItem.ApplicationCode)
            )
    .Size(1000)
    );
var list = results.Documents.ToList();

然后我在上面的行上设置断点。 然后,在Visual Studio立即窗口中,我输入:

?results.ConnectionStatus

它给了我这个:

{StatusCode: 200, 
    Method: POST, 
    Url: http://localhost:9200/_all/searchitem/_search, 
    Request: {
  "size": 1000,
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "lastName": {
              "value": "carr"
            }
          }
        },
        {
          "term": {
            "firstName": {
              "value": "adrian"
            }
          }
        }
      ]
    }
  }
}

希望这有帮助。

答案 4 :(得分:4)

使用最新的弹性搜索5+,我能够得到我的(感谢Adrian Carr的方法)以下内容:

var jsonOutput = System.Text.Encoding.UTF8.GetString(
    response.ApiCall.RequestBodyInBytes
)

这给了我以下输出:

{
   "from":0,
   "size":0,
   "query":{
      "bool":{
      ...
      }
   }
}

答案 5 :(得分:1)

您可以使用EnableTraceConnectionStatusHandler。更多详情here

答案 6 :(得分:1)

嵌套6.2.0

中进行了测试

您现在可以做:

#if DEBUG
  connectionSettings.EnableDebugMode(details =>
  {
    Logger.Debug($"ES Request: {Encoding.UTF8.GetString(details.RequestBodyInBytes ?? new byte[0])}");
    Logger.Verbose($"ES Response: {Encoding.UTF8.GetString(details.ResponseBodyInBytes ?? new byte[0])}");
  });
#endif

调用EnableDebugMode将自动调用DisableDirectStreamingPrettyJson,然后是OnRequestCompleted,并传入您提供的函数。

注意:他们的响应内容中可能存在错误。由于某种原因,该响应似乎缺少一些右括号。

答案 7 :(得分:0)

Elasticsearch.Net和NEST:.NET客户端[7.x]

ref:https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/debug-information.html`

  1. 在ES全局设置中启用DisableDirectStreaming,如下所示。

参考代码

Var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));

var settings = new ConnectionSettings(connectionPool)
    .DisableDirectStreaming(true); 

var client = new ElasticClient(settings);

2。)var response = client.Search<Project>(s =>....)

3。)

var jsonOutput = System.Text.Encoding.UTF8.GetString(
            result.ApiCall.RequestBodyInBytes);

以上内容可以在每个请求的基础上实现,

var response = client.Search<Project>(s => s
    .RequestConfiguration(r => r
        .DisableDirectStreaming() 
    )
    .Query(q => q
        .MatchAll()
    )
);