使用 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 为 1
、3
、5
、7
和 9
的文档,因为它们是前 5 个具有与查询词 "metadata-type-1"
.
匹配的最新 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 为 1
、3
、5
、7
和 9
的文档,因为它们是前 5 个具有与查询词 "metadata-type-1"
.
Timestamp
值的文档