为啥 ElasticSearch Nest Query 中会出现转义反斜杠?

Posted

技术标签:

【中文标题】为啥 ElasticSearch Nest Query 中会出现转义反斜杠?【英文标题】:Why escaping backslashes are appear in ElasticSearch Nest Query?为什么 ElasticSearch Nest Query 中会出现转义反斜杠? 【发布时间】:2020-12-07 11:43:37 【问题描述】:

我正在尝试编写一个 C# 方法来获取控制器的 queryString 并将其转换为 ElasticSearch 查询,如下所示:

public QueryContainerDescriptor<T> Convert<T> (IQueryCollection query) where T: class

    var selector = new QueryContainerDescriptor<T>();
    List<QueryContainer> Must = new List<QueryContainer>();
    foreach(var key in query.keys)
    
        string value = query[key];
        var match = new MatchQuery  Field = $"key.keyword", Query = value ;
        list.Add(match)
    
    selector.Bool(q => q.Must(Must.ToArray()));
    return selector;

它按预期工作,但如果我传递带有反斜杠的 queryString 值,例如:

http://localhost:5000/api/indexData?user=ESKA\\USER

应该转换成这个查询:

 "bool":  "must": [  "match" :  "user.keyword": "ESKA\\USER"   ] 

ElasticSearch 将不会返回任何内容,因为查询的值将是:ESKA\\\\USER,带有 4 个反斜杠,例如:

 "bool":  "must": [  "match" :  "user.keyword": "ESKA\\\\USER"   ] 

我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

我不认为 N​​est 正在执行任何反斜杠转义。这是一个写出请求(和响应,如果使用发送请求的IConnection)的示例

private static void Main()

    var pool = new SingleNodeConnectionPool(new Uri($"http://localhost:9200"));
    var settings = new ConnectionSettings(pool, new InMemoryConnection())
        .DefaultIndex("default_index")
        .DisableDirectStreaming()
        .PrettyJson()
        .OnRequestCompleted(callDetails =>
        
            if (callDetails.RequestBodyInBytes != null)
            
                var json = JObject.Parse(Encoding.UTF8.GetString(callDetails.RequestBodyInBytes));
    
                Console.WriteLine(
                    $"callDetails.HttpMethod callDetails.Uri \n" +
                    $"json.ToString(Newtonsoft.Json.Formatting.Indented)");
            
            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);
    
    var collection = new QueryCollection(new Dictionary<string, StringValues>
    
         "user", "ESKA\\USER" 
    );
    
    var response = client.Search<object>(s => s
        .Query(q => Convert<object>(q, collection))
    );


public static QueryContainerDescriptor<T> Convert<T>(QueryContainerDescriptor<T> selector, IQueryCollection query) where T : class

    List<QueryContainer> Must = new List<QueryContainer>();
    foreach (var key in query.Keys)
    
        string value = query[key];
        var match = new MatchQuery  Field = $"key.keyword", Query = value ;
        Must.Add(match);
    
    selector.Bool(q => q.Must(Must.ToArray()));
    return selector;

结果查询是

POST http://localhost:9200/default_index/_search?pretty=true&typed_keys=true 

  "query": 
    "bool": 
      "must": [
        
          "match": 
            "user.keyword": 
              "query": "ESKA\\USER"
            
          
        
      ]
    
  

如果user 的值是verbatim string literal @"ESKA\\USER",那么生成的查询将是

"user.keyword": 
    "query": "ESKA\\\\USER"

因为逐字字符串文字中的每个\ 都需要转义。

【讨论】:

以上是关于为啥 ElasticSearch Nest Query 中会出现转义反斜杠?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 ElasticSearch Nest 客户端会为 MultiPolygonGeoShape 抛出 invalid_shape_exception

ElasticSearch NEST 搜索

NEST (ElasticSearch) 将 Highlights 匹配到文档

ElasticSearch NEST笔记

Elasticsearch,如何使 NEST 地图响应类

使用 NEST (ElasticSearch) 插入文档