【ElasticSearch Nest】入门
介绍
Elasticsearch 官方为 .NET 提供了 2 个官方客户端库:Elasticsearch.Net
和 NEST
。
Elasticsearch.Net
和 NEST
对比说明:
- 可以简单理解为
Elasticsearch.Net
是NEST
的一个子集。 NEST
内部使用了ElasticSearch.Net
,并通过NEST
可以对外暴露ElasticSearch.Net
客户端。NEST
包含了ElasticSearch.Net
所没有的一些高级功能,如:- 强类型查询 DSL:可以将所有请求和响应的对象类型转换 1:1 的.NET 类型。
- 自动转换为 CLR 的数据类型。
基本上 .NET 项目到了要使用上
ElasticSearch.Net
的地步,直接选择NEST
即可。
在使用 NEST 作为客户端的时候,建议将ElasticClient
对象作为单例来使用。
ElasticClient 被设计为线程安全。
ES 中的缓存是根据 ConnectionSettings 来划分的,即服务端缓存针对的是每一个 ConnectionStrings
入门案例
{
var settings = new ConnectionSettings(new Uri("http://123.56.57.211:9200")).DefaultIndex("index1");
settings.DefaultMappingFor<People>(m => m.IndexName("index2"));//People类型对应索引库index2
settings.DefaultMappingFor<People3>(m => m.IndexName("index5"));//People3类型对应索引库index5
ElasticClient client = new ElasticClient(settings);
//查询
var searchResponse = client.Search<People>();//查询index2数据库
var searchResponse2 = client.Search<People2>();//查询默认数据库index1
//全部索引中查询
var searchResponse3 = client.Search<People>(q => q.AllIndices());
//指定索引库中查询
var searchResponse4 = client.Search<People>(q => q.Index("index1"));
//SearchRequest查询
var searchRequest = new SearchRequest
{
From = 0,
Size = 3,
Query = new TermQuery
{
Field = Infer.Field<People2>(p => p.Age),
Value = 2
}
};
var searchResponse5 = client.Search<People2>(searchRequest);
//LowLevelClient查询
var searchResponse6 = client.LowLevel.Search<SearchResponse<People2>>("index1", PostData.Serializable(new
{
from = 0,
size = 10,
query = new
{
match = new
{
age = 2
}
}
}));
//聚合查询
var searchResponse7 = client.Search<People2>(q => q.MatchAll()
.Aggregations(a => a.Terms("age_bucket", ag => ag.Field(ag => ag.Age))));
//创建索引库,自动映射
client.Indices.Create("index5", i => i.Map<People3>(m => m.AutoMap()));
var indexResponse2 = client.IndexDocument<People3>(new People3 { Id = 4, Names = new List<Name> { new Name { Firstname = "wj", Lastname = "f" }, new Name { Firstname = "wj2", Lastname = "f2" } } });
}
查询
{
var settings = new ConnectionSettings(new Uri("http://123.56.57.211:9200")).DefaultIndex("index1");
ElasticClient client = new ElasticClient(settings);
//term
var searchResponse = client.Search<People>(s =>
s.Query(q =>
q.Term(p=>p.Field(f=>f.Age).Value(2))
)
);
//match
searchResponse = client.Search<People>(s =>
s.Query(q =>
q.Match(m=>m.Field(f => f.Description).Query("lm"))
)
);
//multi_match
searchResponse = client.Search<People>(s =>
s.Query(q =>
q.MultiMatch(m=>m.Query("lm").Fields(f=>f.Field(ff=>ff.Name).Field(ff=>ff.Description)))
)
);
组合查询(bool)
将多个查询条件组合在一起,形成复杂查询
//bool查询
//且(&& Mush)
searchResponse = client.Search<People>(s =>
s.Query(q =>
q.Bool(b =>
b.Must(
m => m.Term(t => t.Age, 4),
m => m.Term(t => t.Description.Suffix("keyword"), "jk lm")
)
)
)
);
可以使用重载运算符简化bool查询:
searchResponse = client.Search<People>(s =>
s.Query(q =>
q.Term(p => p.Age, 4) && q.Term(p => p.Description.Suffix("keyword"), "jk lm")
)
);
//或(|| Should)
searchResponse = client.Search<People>(s =>
s.Query(q =>
q.Term(p => p.Age, 4) || q.Term(p => p.Description.Suffix("keyword"), "jk lm")
)
);
//非(! must_not)
searchResponse = client.Search<People>(s =>
s.Query(q =>
!q.Term(p => p.Age, 4) && !q.Term(p => p.Age, 2)
)
);
//过滤(+ filter)通过使用一元“+”运算符可以将查询转换为带有过滤子句的布尔查询。
searchResponse = client.Search<People>(s =>
s.Query(q =>
+q.Term(p => p.Age, 4)
)
);
//假设你有很多 must、should 子句,使用“&=”、“|=”进行合并
QueryContainer c = new QueryContainer();
for (var i = 1; i < 5; i++)
{
c |= new TermQuery { Field = "age", Value = i };
}
searchResponse = client.Search<People>(s =>
s.Query(q => c)
);
}
除了运算符重载还可以使用对象初始化程序语法:
var secondSearchResponse = client.Search<Project>(new SearchRequest<Project>
{
Query = new TermQuery { Field = Field<Project>(p => p.Name), Value = "x" } ||
new TermQuery { Field = Field<Project>(p => p.Name), Value = "y" }
});
返回部分字段
{
var settings = new ConnectionSettings(new Uri("http://123.56.57.211:9200")).DefaultIndex("index1");
ElasticClient client = new ElasticClient(settings);
//不返回_source
var searchResponse = client.Search<People>(s => s.Source(false).Query(q => q.MatchAll()));
//只返回id、age
searchResponse = client.Search<People>(s => s.Source(sf => sf.Includes(i => i.Fields(f => f.Id, f => f.Age))).Query(q => q.MatchAll()));
//不返回Name
searchResponse = client.Search<People>(s => s.Source(sf => sf.Excludes(i => i.Fields("name*"))).Query(q => q.MatchAll()));
}
聚合
{
var settings = new ConnectionSettings(new Uri("http://123.56.57.211:9200")).DefaultIndex("index1");
ElasticClient client = new ElasticClient(settings);
////添加索引
//var indexResponse = client.IndexDocument<People>(new People { Id = 1, Age = 2,Description="ab cd", Name = new Name { Firstname = "wj1", Lastname = "f1" } });
// indexResponse = client.IndexDocument<People>(new People { Id = 2, Age = 3, Description = "cd ef", Name = new Name { Firstname = "wj2", Lastname = "f2" } });
// indexResponse = client.IndexDocument<People>(new People { Id = 3, Age = 4, Description = "ef gh", Name = new Name { Firstname = "wj3", Lastname = "f3" } });
// indexResponse = client.IndexDocument<People>(new People { Id = 4, Age = 5, Description = "hi jk", Name = new Name { Firstname = "wj4", Lastname = "f4" } });
//indexResponse = client.IndexDocument<People>(new People { Id = 5, Age = 4, Description = "jk lm", Name = new Name { Firstname = "wj4", Lastname = "f4" } });
//平均数、最大、最小(指标聚合,相当于数据库中的聚合函数)
var searchResponse = client.Search<People>(p => p.Size(0).Aggregations(a => a.Average("age_avg", f => f.Field(p => p.Age))
.Max("age_max", f => f.Field(p => p.Age))
.Min("age_min", f => f.Field(p => p.Age))
));
//按年龄分组(桶聚合,相当于数据库中的GroupBy)
searchResponse = client.Search<People>(p => p.Size(0).Aggregations(a => a.Terms("age_bucket", t => t.Field(p => p.Age))));
//取每个年龄的最大id
searchResponse = client.Search<People>(p => p.Size(0).Aggregations(a => a.Terms("age_bucket", t => t.Field(p => p.Age).Aggregations(a => a.Max("age_max", f => f.Field(p => p.Id))))));
}
参考:
https://blog.zhuliang.ltd/2020/01/backend/Elasticsearch-Nest-QuickStart.html
https://blog.csdn.net/WuLex/article/details/71375446