NEST V7.12.1 - 检测到类型为“Elasticsearch.Net.ApiCallDetails”的属性“response”的自引用循环

问题描述

我对 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 复制错误,但无法复制。然而,正则表达式存在一些问题;

  1. 封闭的 /g 修饰符无效或受 the regular expression engine 支持,可以省略。
  2. 由于正则表达式的值为 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
}
  1. 我认为 . 也需要转义(否则匹配任何字符)。

综合起来,这是一个工作示例

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

的文档

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...