你如何调试你的 Nest 查询?
How do you debug your Nest queries?
我是 Nest 的新手,我很可能不会像我想的那样创建我的查询。我的问题更像是授人以鱼不如授人以渔。但是,我将以我当前的问题为例。
我在 ElasticSearch 中有几个 Series
类型的文档。我将在没有属性和 public 修饰符的情况下将其存根,仅包含与查询相关的信息:
class Series
{
string Id {get; set;}
DateTime StartDate {get; set;}
DateTime EndDate {get; set;}
HashSet<Role> ReleasableTo {get; set;}
}
这些都很好,很漂亮。我可以 Get()
一个 Series
对象没问题。我 运行 遇到的问题是试图弄清楚 Nest 如何格式化我的查询。我的近期目标是找到可发布到 Role.Visitor
的最新 Series
。我这样设置 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
的系列,按结束日期反向排序,并将结果限制为一个回来了。那正是我想要的。在我拥有的数以千计的 Series 记录中,大约 90% 符合此配置文件。不幸的是,查询 returns 0 个结果。没有错误,只是没有结果。我不知道的是我是否错误地使用了 API,Nest 是否生成了一个没有意义的查询结构,或者我只是对 ElasticSearch 不够了解。当我删除 Filter
子句时,我得到了一个结果,但我不能保证每个人都可以看到它。
如何查看 Nest 生成并发送到 ElasticSearch 的 JSON?
您可以获取搜索请求 URL 和 JSON 请求正文的值,如下所示:
var requestURL = response.RequestInformation.RequestUrl;
var jsonBody = Encoding.UTF8.GetString(response.RequestInformation.Request);
您可以在 RequestInformation
中找到其他有用的属性以进行调试。
您可以使用 EnableTrace
或 ConnectionStatusHandler
。更多详情 here.
我想比 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 节点。
真的很容易。如果这是我搜索的代码:
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 立即 Window 中,我输入:
?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"
}
}
}
]
}
}
}
希望对您有所帮助。
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);
}
}
使用最新的 elastic search 5+,我能够通过以下方式获得我的(感谢 Adrian Carr 的方法):
var jsonOutput = System.Text.Encoding.UTF8.GetString(
response.ApiCall.RequestBodyInBytes
)
这给了我以下输出:
{
"from":0,
"size":0,
"query":{
"bool":{
...
}
}
}
在 Nest 6.2.0
中测试
调用EnableDebugMode
会自动调用DisableDirectStreaming
、PrettyJson
,然后OnRequestCompleted
,传入你给它的lambda。
所以,现在您可以执行以下操作:
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])}");
});
注意:对我来说,回复似乎缺少右括号。似乎嵌套响应中的某处可能存在错误。除了日志记录之外似乎没有任何影响。
Elasticsearch.Net 和 NEST:.NET 客户端 [7.x]
参考:https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/debug-information.html`
- 在 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()
)
);
在我当前的 Elasticsearch 版本中。NET/NEST (7.13.2),我可以捕捉 ElasticsearchClientException
并利用 DebugInformation
。如果 DisableDirectStreaming
像其他答案一样设置,则包含完整的请求正文。
try {
// do some elastic stuff
} catch (ElasticsearchClientException e) {
Logger.LogInformation(e.DebugInformation);
// handle error
}
我是 Nest 的新手,我很可能不会像我想的那样创建我的查询。我的问题更像是授人以鱼不如授人以渔。但是,我将以我当前的问题为例。
我在 ElasticSearch 中有几个 Series
类型的文档。我将在没有属性和 public 修饰符的情况下将其存根,仅包含与查询相关的信息:
class Series
{
string Id {get; set;}
DateTime StartDate {get; set;}
DateTime EndDate {get; set;}
HashSet<Role> ReleasableTo {get; set;}
}
这些都很好,很漂亮。我可以 Get()
一个 Series
对象没问题。我 运行 遇到的问题是试图弄清楚 Nest 如何格式化我的查询。我的近期目标是找到可发布到 Role.Visitor
的最新 Series
。我这样设置 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
的系列,按结束日期反向排序,并将结果限制为一个回来了。那正是我想要的。在我拥有的数以千计的 Series 记录中,大约 90% 符合此配置文件。不幸的是,查询 returns 0 个结果。没有错误,只是没有结果。我不知道的是我是否错误地使用了 API,Nest 是否生成了一个没有意义的查询结构,或者我只是对 ElasticSearch 不够了解。当我删除 Filter
子句时,我得到了一个结果,但我不能保证每个人都可以看到它。
如何查看 Nest 生成并发送到 ElasticSearch 的 JSON?
您可以获取搜索请求 URL 和 JSON 请求正文的值,如下所示:
var requestURL = response.RequestInformation.RequestUrl;
var jsonBody = Encoding.UTF8.GetString(response.RequestInformation.Request);
您可以在 RequestInformation
中找到其他有用的属性以进行调试。
您可以使用 EnableTrace
或 ConnectionStatusHandler
。更多详情 here.
我想比 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 节点。
真的很容易。如果这是我搜索的代码:
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 立即 Window 中,我输入:
?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"
}
}
}
]
}
}
}
希望对您有所帮助。
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);
}
}
使用最新的 elastic search 5+,我能够通过以下方式获得我的(感谢 Adrian Carr 的方法):
var jsonOutput = System.Text.Encoding.UTF8.GetString(
response.ApiCall.RequestBodyInBytes
)
这给了我以下输出:
{
"from":0,
"size":0,
"query":{
"bool":{
...
}
}
}
在 Nest 6.2.0
中测试调用EnableDebugMode
会自动调用DisableDirectStreaming
、PrettyJson
,然后OnRequestCompleted
,传入你给它的lambda。
所以,现在您可以执行以下操作:
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])}");
});
注意:对我来说,回复似乎缺少右括号。似乎嵌套响应中的某处可能存在错误。除了日志记录之外似乎没有任何影响。
Elasticsearch.Net 和 NEST:.NET 客户端 [7.x]
参考:https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/debug-information.html`
- 在 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()
)
);
在我当前的 Elasticsearch 版本中。NET/NEST (7.13.2),我可以捕捉 ElasticsearchClientException
并利用 DebugInformation
。如果 DisableDirectStreaming
像其他答案一样设置,则包含完整的请求正文。
try {
// do some elastic stuff
} catch (ElasticsearchClientException e) {
Logger.LogInformation(e.DebugInformation);
// handle error
}