问题描述
我对 ElasticSearch 还很陌生,我目前正在尝试使用它,但是在尝试进行正则表达式查询时,它会出现以下错误:
Newtonsoft.Json.JsonSerializationException:检测到类型为“Elasticsearch.Net.ApiCallDetails”的属性“response”的自引用循环。路径“apiCall.originalException”。 在 Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CheckForCircularReference(JsonWriter writer,Object value,JsonProperty property,JsonContract contract,JsonContainerContract containerContract,JsonProperty containerProperty) 在 Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer,JsonContainerContract contract,JsonProperty member,JsonContract& memberContract,Object& memberValue) ......
查询:
var ChildFileItems = Elasticclient.Search<FileData>(s => s
//.From(0).Size(10)
.Query(q => q
.Regexp(r => r
.Field(p => p.FilePath)
//.Value($"/{SearchPath}\\\\([A-Z a-z0-9_.-]+)[.]([A-Z a-z0-9]+)/g")
.Value(@$"/([A-Z a-z:0-9_.\\-]+)/g")
)
)
);
(我只是想让任何正则表达式查询工作)。 当我执行一个没有找到任何结果的正则表达式查询时,它没有给出任何错误,所以它(我猜)是我的对象中的一些东西。在网上我发现你可以忽略这个错误,但是这些都是针对版本 6 的,我不能让它在版本 7 中工作。这是最好的(阅读:我没有错误)版本,但是有了这个我仍然得到错误。
当我执行“正常”匹配查询时,它确实工作正常并且我得到了我的结果。
var settings = new ConnectionSettings(pool,(builtInSerializer,connectionSettings) =>
new JsonNetSerializer(builtInSerializer,connectionSettings,() => new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
}))
.DefaultFieldNameInferrer(p => p)
.PrettyJson();
;
解决方法
错误很奇怪;它是一个 Newtonsoft.Json.JsonSerializationException
,但 7.12.1 客户端在内部不使用 Newtonsoft.Json。
使用 Newtonsoft.Json 的序列化程序可以根据您的第二个代码示例配置 JsonNetSerializer
,但此序列化程序用于反序列化您的文档,不会用于反序列化 Elasticsearch.Net.ApiCallDetails
,这是一种低级客户端类型。
我尝试使用 Nest 7.12.1 复制错误,但无法复制。然而,正则表达式存在一些问题;
- 封闭的
/
和g
修饰符无效或受 the regular expression engine 支持,可以省略。 - 由于正则表达式的值为 verbatim string,因此在查询中发送时
\\
是文字\\\\
,这会导致错误:
// Request
POST http://localhost:9200/default_index/_search?pretty=true&typed_keys=true
{
"query": {
"regexp": {
"FilePath": {
"value": "/([A-Z a-z:0-9_.\\\\-]+)/g"
}
}
}
}
// Response
Status: 400
{
"error" : {
"root_cause" : [
{
"type" : "query_shard_exception","reason" : "failed to create query: expected ']' at position 24","index_uuid" : "83Lsg5kRR32c6iSK-1L5rw","index" : "default_index"
}
],"type" : "search_phase_execution_exception","reason" : "all shards failed","phase" : "query","grouped" : true,"failed_shards" : [
{
"shard" : 0,"index" : "default_index","node" : "1k1iMRXORXSEKvOH4Iz46Q","reason" : {
"type" : "query_shard_exception","caused_by" : {
"type" : "illegal_argument_exception","reason" : "expected ']' at position 24"
}
}
}
]
},"status" : 400
}
- 我认为
.
也需要转义(否则匹配任何字符)。
综合起来,这是一个工作示例
private static void Main()
{
var defaultIndex = "default_index";
var pool = new SingleNodeConnectionPool(new Uri($"http://localhost:9200"));
var settings = new ConnectionSettings(pool,JsonNetSerializer.Default)
.DefaultIndex(defaultIndex)
.DefaultFieldNameInferrer(p => p)
// The following settings are useful during development but come
// with overhead and so likely don't want them in production.
.DisableDirectStreaming()
.PrettyJson()
.OnRequestCompleted(callDetails =>
{
// Added this so that you can see the requests/responses to and
// from Elasticsearch.
if (callDetails.RequestBodyInBytes != null)
{
var serializer = new JsonSerializer();
var jObjects = new List<JObject>();
using (var sr = new StringReader(Encoding.UTF8.GetString(callDetails.RequestBodyInBytes)))
using (var jsonTextReader = new JsonTextReader(sr))
{
jsonTextReader.SupportMultipleContent = true;
while (jsonTextReader.Read())
jObjects.Add((JObject)JObject.ReadFrom(jsonTextReader));
}
var formatting = jObjects.Count == 1
? Newtonsoft.Json.Formatting.Indented
: Newtonsoft.Json.Formatting.None;
var json = string.Join("\n",jObjects.Select(j => j.ToString(formatting)));
Console.WriteLine($"{callDetails.HttpMethod} {callDetails.Uri} \n{json}");
}
else
{
Console.WriteLine($"{callDetails.HttpMethod} {callDetails.Uri}");
}
Console.WriteLine();
if (callDetails.ResponseBodyInBytes != null)
{
Console.WriteLine($"Status: {callDetails.HttpStatusCode}\n" +
$"{Encoding.UTF8.GetString(callDetails.ResponseBodyInBytes)}\n" +
$"{new string('-',30)}\n");
}
else
{
Console.WriteLine($"Status: {callDetails.HttpStatusCode}\n" +
$"{new string('-',30)}\n");
}
});
var client = new ElasticClient(settings);
if (client.Indices.Exists(defaultIndex).Exists)
client.Indices.Delete(defaultIndex);
client.Bulk(b => b
.Index(defaultIndex)
.IndexMany(new [] {
new FileData { FilePath = "Foo.jpg" },new FileData { FilePath = "^$%*#@" },})
.Refresh(Refresh.WaitFor)
);
var searchResponse = client.Search<FileData>(s => s
.Query(q => q
.Regexp(r => r
.Field(p => p.FilePath)
.Value(@"([A-Z a-z:0-9_\.\-]+)")
)
)
);
}
public class FileData
{
public string FilePath {get;set;}
}
找到文件路径为 Foo.jpg