我有logstash将日志推送到elasticsearch,自动将@timestamp
字段插入每个文档。我在此项目中使用了Elasticsearch.Net
而不是NEST
。
每个文档看起来像:
{
"Origin": 0,
"VisitorId": "49f843eb-be38-4912-a3b8-277841cd709d",
"CompanyId": 1,
"ActivityType": 21,
"Referer": "http://cn.bing.com/search?q=sogou&src=IE-SearchBox&FORM=IE10SR",
"ProductId": 1,
"version": "1.0",
"Url": "http://localhost:8001/Product/Detail/1",
"DeviceType": 1,
"@timestamp": "2017-03-21T02:04:13.136Z",
"UserId": 4,
"host": "ZBL-PC",
"@version": "1",
"IpAddress": "14.197.145.136",
"timestamp": "2017-03-21T02:04:13.136Z"
}
目前,我的搜索查询如下:
var res = client.SearchAsync<SearchResult<ProductVisit>>(index: _indexName,
type: "viewsingleproduct",
body: new PostData<object>(new
{
size = 10
}));
public class ProductVisit
{
public int? UserId { get; set; }
public Guid? VisitorId { get; set; }
public int DeviceType { get; set; }
public string timestamp { get; set; }
public int CompanyId { get; set; }
public long ProductId { get; set; }
}
public class Hit<TDocument>
{
public TDocument _source { get; set; }
}
public class Hits<TDocument>
{
public int total { get; set; }
public List<Hit<TDocument>> hits { get; set; }
}
public class SearchResult<TDocument>
{
public Hits<TDocument> hits { get; set; }
}
检索文档的Elasticsearch.Net
方法是声明一个DTO,它可以从响应中的json自动反序列化。但是,在这种情况下,我不能声明属性是有效的C#属性名称,以便可以填充@timestamp
值。
在使用Newtonsoft.json的Nest
中,我可以通过属性注释在elasticsearch中指定实际的字段名称(我记得JsonProperty
将执行该技巧,并且NEST也有自己的属性,允许您指定财产名称)。但是,Elasticsearch.Net
内部不使用Newtonsoft.json。它使用SimpleJson
,它可以通过DataMember
属性支持类似的技巧,但它需要启用SIMPLE_JSON_DATACONTRACT
预处理器切换,默认情况下Elasticsearch.Net
禁用它。
目前我的解决方案是将@timestamp
字段复制到logstash配置中的timestamp
,如上面的json doc所示。但这是一个黑客攻击。
我最初在请求方遇到问题,官方示例主要使用匿名类型构建查询:
new
{
term = new
{
_TopicPostId = new {
value = 4
}
}
},
但偶尔我需要构造包含特殊字符的字段名称的查询。我终于想通了我可以使用Dictionary而不是匿名类型而且它有效。例如:
new {
range = new Dictionary<string, object>{{
"@timestamp",
new
{
gte = "now-1d/d",
lte = "now/d"
}
}}
},