使用 ElasticSearch (C#/NEST) 获取按时间戳排序的所有文档

With ElasticSearch (C#/NEST) get all documents sorted by timestamp

我有一个 elasticsearch 数据库,其中的类型和时间戳字段定义为:

public Common.MediaType Type        { get; set; }
public DateTime Timestamp           { get; set; }

如何查询 return X 个条目,匹配特定类型并按时间戳排序?

如果我这样做:

        var Match = Index.Driver.Search<Metadata>(_ => _
            .Query(Q => Q.Term(P => P.Type, Type))
            .Size(NumberOfItems)
            .Sort(Q => Q.Descending(P => P.Timestamp)));

它会失败,因为它会 return NumberOfItems 条正确类型的记录,然后按时间戳对它们进行排序,所以它很可能会错过带有最新时间戳。

我想要的是使时间戳成为查询的一部分,以便我得到 NumberOfItems 条按 TimeStamp 排序的匹配正确的类型。

但是我不知道怎么写...

您可能想使用 Take 而不是 Size。

var Match = Index.Driver.Search<Metadata>(_ => _
            .Query(Q => Q.Term(P => P.Type, Type))
            .Take(NumberOfItems)
            .Sort(Q => Q.Descending(P => P.Timestamp)));

这应该先排序,然后取第一个 NumberOfItems 个文件。

为了让我理解正确,集群内所有索引中具有最新时间戳的前 5 Metadata 文档类型?

如果这就是您想要的,那么下面的方法就可以了

var Type = "metadata-type";
var NumberOfItems = 5;

var searchResponse = client.Search<Metadata>(s => s
    .AllIndices()
    .Query(q => q
        .Term(f => f.Type, Type)
    )
    .Size(NumberOfItems)
    .Sort(sort => sort
        .Descending(f => f.Timestamp)
    )
);

AllIndices() 将在所有索引中搜索 Metadata 文档类型。如果只想在一个特定索引或多个特定索引中搜索,则可以将 AllIndices() 替换为

.Index("index-1,index-2")

其中参数是要搜索的索引名称的逗号分隔列表。

您需要考虑的一点是,索引到 Elasticsearch 的文档与可用于搜索结果的文档之间存在间隔。默认情况下,此间隔为 1 秒,这是可以设置的最短时间。

编辑:

来自您的评论:

currently, If all records are of the right type and I want 5 items, it will take the first 5 and sort them; but maybe record 6 had a higher timestamp value but it will not be included in the result of the query matching the type.

Elasticsearch 将如何获取 前 5 项?它将首先根据某个值对项目进行排序,在这种情况下,它将根据查询中指定的时间戳降序排序,然后是 return 前 5 个文档。 这不会暗示文档的任意排序,取前 5 个,然后按时间戳降序仅对这 5 个排序。

这里有一个例子来演示

void Main()
{
    var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
    var defaultIndex = "default-index";
    var connectionSettings = new ConnectionSettings(pool)
            .DefaultIndex(defaultIndex);

    var client = new ElasticClient(connectionSettings);

    if (client.IndexExists(defaultIndex).Exists)
        client.DeleteIndex(defaultIndex);

    client.CreateIndex(defaultIndex, c => c
        .Mappings(m => m
            .Map<Metadata>(mm => mm.AutoMap())
        )
    );

    var metadata = Enumerable.Range(1, 1000).Select(i =>
        new Metadata
        {
            Id = i,
            Timestamp = DateTime.UtcNow.Date.AddDays(-(i-1)),
            Type = i % 2 == 0? "metadata-type-2" : "metadata-type-1"
        });

    client.IndexMany(metadata);
    client.Refresh(defaultIndex);

    var Type = "metadata-type-1";
    var NumberOfItems = 5;

    var searchResponse = client.Search<Metadata>(s => s
        .Query(q => q
            .Term(f => f.Type, Type)
        )
        .Size(NumberOfItems)
        .Sort(sort => sort
            .Descending(f => f.Timestamp)
        )
    );
}

public class Metadata
{
    public int Id { get; set;}

    public DateTime Timestamp { get; set;}

    [String(Index = FieldIndexOption.NotAnalyzed)]
    public string Type { get; set;}
}

对于搜索响应,我们返回

{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 500,
    "max_score" : null,
    "hits" : [ {
      "_index" : "default-index",
      "_type" : "metadata",
      "_id" : "1",
      "_score" : null,
      "_source" : {
        "id" : 1,
        "timestamp" : "2016-07-01T00:00:00Z",
        "type" : "metadata-type-1"
      },
      "sort" : [ 1467331200000 ]
    }, {
      "_index" : "default-index",
      "_type" : "metadata",
      "_id" : "3",
      "_score" : null,
      "_source" : {
        "id" : 3,
        "timestamp" : "2016-06-29T00:00:00Z",
        "type" : "metadata-type-1"
      },
      "sort" : [ 1467158400000 ]
    }, {
      "_index" : "default-index",
      "_type" : "metadata",
      "_id" : "5",
      "_score" : null,
      "_source" : {
        "id" : 5,
        "timestamp" : "2016-06-27T00:00:00Z",
        "type" : "metadata-type-1"
      },
      "sort" : [ 1466985600000 ]
    }, {
      "_index" : "default-index",
      "_type" : "metadata",
      "_id" : "7",
      "_score" : null,
      "_source" : {
        "id" : 7,
        "timestamp" : "2016-06-25T00:00:00Z",
        "type" : "metadata-type-1"
      },
      "sort" : [ 1466812800000 ]
    }, {
      "_index" : "default-index",
      "_type" : "metadata",
      "_id" : "9",
      "_score" : null,
      "_source" : {
        "id" : 9,
        "timestamp" : "2016-06-23T00:00:00Z",
        "type" : "metadata-type-1"
      },
      "sort" : [ 1466640000000 ]
    } ]
  }
}

我们按顺序返回 ID 为 13579 的文档,因为它们是前 5 个具有与查询词 "metadata-type-1".

匹配的最新 Timestamp 值的文档