NEST - 低级搜索不返回日期。

问题描述 投票:0回答:1

我有一个C#控制台应用程序,我使用NEST来索引数据并在ElasticSearch中进行搜索。

版本。

  • ElasticSearch 7.5.2
  • .NET 4.7.2
  • NEST 7.6.1

当我使用NEST进行搜索时,一切都很正常。但是在一些特殊情况下,我想使用NEST的低级搜索(因为我可以使用sql命令)。但是在低级搜索中,并没有获得Timestamp。下面是代码示例。

class EsObject
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime Timestamp { get; set; }

    public override string ToString()
    {
        return $"Id = {Id}, Name = {Name}, Timestamp = {Timestamp.ToString("dd.MM.yyyy HH:mm:ss")}";
    }
}

class Program
{
    static void Main(string[] args)
    {
        var indexName = "es_objects";
        //
        // Create data objects
        //
        var obj = new EsObject()
        {
            Id = 1,
            Name = "Object_1",
            Timestamp = new DateTime(2020, 2, 12, 4, 55, 19)
        };
        Console.WriteLine($"Object created {obj}");

        //
        // Connect to ElasticSearch
        //
        Console.Write("Connecting to ElasticSearch... ");
        var node = new Uri("http://localhost:9200");
        var settings = new ConnectionSettings(node)
            .DefaultIndex(indexName)
            .DefaultMappingFor<EsObject>(x => x.IdProperty("Id"))
            .DefaultFieldNameInferrer(s => s.ToLower()); ;

        var esClient = new ElasticClient(settings);
        Console.WriteLine("done");

        //
        // Index data
        //
        Console.Write("Indexing data... ");
        var idxResp = esClient.IndexDocument(obj);
        Console.WriteLine("done");

        //
        // Searching using NEST
        //
        Console.Write("Searching data using NEST ... ");
        var result = esClient.Search<EsObject>(s => s
                        .Query(q => q
                            .Match(m => m
                                .Field(f => f.Name)
                                    .Query(obj.Name))))
                        .Documents
                        .ToList();

        Console.WriteLine("done");
        Console.WriteLine($"Results: found {result.Count} items");
        if (result.Count > 0)
            Console.WriteLine($"Found item: {result[0]}");

        //
        // Searching using SQL
        //
        Console.Write("Searching data using low level ... ");
        var request = new TranslateSqlRequest
        {
            Query = $"select * from {indexName} where name='{obj.Name}'"
        };

        var sqlResponse = esClient.LowLevel.Sql.Translate<StringResponse>(PostData.Serializable(request));
        var resp = esClient.LowLevel.Search<SearchResponse<EsObject>>(indexName, sqlResponse.Body).Documents.ToList();
        Console.WriteLine("done");
        Console.WriteLine($"Results: found {resp.Count} items");
        if (resp.Count > 0)
            Console.WriteLine($"Found item: {resp[0]}");

        Console.ReadKey();
    }
}

当我运行程序时,我得到以下结果。

Object created Id = 1, Name = Object_1, Timestamp = 12.02.2020 04:55:19
Connecting to ElasticSearch... done
Indexing data... done
Searching data using NEST ... done
Results: found 1 items
Found item: Id = 1, Name = Object_1, Timestamp = 12.02.2020 04:55:19
Searching data using low level ... done
Results: found 1 items
Found item: Id = 1, Name = Object_1, Timestamp = 01.01.0001 00:00:00

有什么办法可以让我在使用低级搜索时获得正确的日期值?

c# elasticsearch nest
1个回答
1
投票

由SQL翻译API生成的查询看起来是这样的。

{
  "size" : 1000,
  "query" : {
    "term" : {
      "name.keyword" : {
        "value" : "Object_1",
        "boost" : 1.0
      }
    }
  },
  "_source" : {
    "includes" : [
      "name"
    ],
    "excludes" : [ ]
  },
  "docvalue_fields" : [
    {
      "field" : "id"
    },
    {
      "field" : "timestamp",
      "format" : "epoch_millis"
    }
  ],
  "sort" : [
    {
      "_doc" : {
        "order" : "asc"
      }
    }
  ]
}

关键的是,源头过滤是为了只返回 name 领域中 _source 文件,并 idtimestamp 正在从 docvalue_fields. 要从搜索响应中获取这些信息,你需要从下面的 fields 每打

var resp = client.LowLevel.Search<SearchResponse<EsObject>>(indexName, sqlResponse.Body);

var documents = resp.Hits
    .Select(h => {
        h.Source.Id = h.Fields.ValueOf<EsObject, int>(f => f.Id);   
        h.Source.Timestamp = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(h.Fields.Value<string>("timestamp"))).DateTime;
        return h.Source;
    })
    .ToList();

供参考,以下是搜索响应的JSON格式

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [
      {
        "_index" : "es_objects",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : null,
        "_source" : {
          "name" : "Object_1"
        },
        "fields" : {
          "id" : [
            1
          ],
          "timestamp" : [
            "1581483319000"
          ]
        },
        "sort" : [
          0
        ]
      }
    ]
  }
}

一个能满足你需求的搜索查询

var resp = client.Search<EsObject>(s => s
    .Query(q => q
        .Term(f => f.Name.Suffix("keyword"), obj.Name)
    )
    .Sort(s => s.Ascending(SortSpecialField.DocumentIndexOrder))
);

var documents = resp.Documents.ToList();
© www.soinside.com 2019 - 2024. All rights reserved.