【愚公系列】2022年05月 .NET架构班 065-分布式中间件 .Net Core下使用Elasticsearch落地情况分
【摘要】 一、.Net Core下使用Elasticsearch落地情况分析 1.查询商品业务场景落地ProductController类中添加代码/// <summary>/// 商品控制器/// </summary>[ApiController][Route("Product")]public class ProductController : ControllerBase{ privat...
一、.Net Core下使用Elasticsearch落地情况分析
1.查询商品业务场景落地
ProductController类中添加代码
/// <summary>
/// 商品控制器
/// </summary>
[ApiController]
[Route("Product")]
public class ProductController : ControllerBase
{
private readonly IProductService _productService;
public ProductController(IProductService productService)
{
_productService = productService;
}
/// <summary>
/// 搜索商品
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpGet("{id}")]
public ActionResult<Product> GetProduct(string id)
{
var product = _productService.GetProductById(id);
if (product == null)
{
return NotFound();
}
return product;
}
}
ProductService 服务类
/// <summary>
/// 商品服务实现
/// </summary>
public class ProductService : IProductService
{
private readonly IMongoCollection<Product> _products;
public ProductService()
{
#region 1、单实例连接
{
var node = new Uri("http://localhost:9200");
// var defaultIndex = "products";
var settings = new ConnectionSettings(node);
//.DefaultIndex(defaultIndex);
elasticClient = new ElasticClient(settings);
}
#endregion
}
public Product GetProductById(string id)
{
return elasticClient.Get<Product>(id, idx => idx.Index("products")).Source;
}
}
2.搜索商品业务场景落地
/// <summary>
/// 商品控制器
/// </summary>
[ApiController]
[Route("Product")]
public class ProductController : ControllerBase
{
private readonly IProductService _productService;
public ProductController(IProductService productService)
{
_productService = productService;
}
/// <summary>
/// 全文查询
/// </summary>
/// <param name="productDto"></param>
/// <returns></returns>
[HttpGet("KeywordSearch")]
public ActionResult<IEnumerable<Product>> GetProductsKeywordSearch([FromQuery]ProductDto productDto)
{
var products = _productService.GetProductsKeywordSearch(productDto);
if (products == null)
{
return NotFound();
}
return products.ToList();
}
}
二、.Net Core下使用Elasticsearch的封装
1.nuget包
NEST
2.控制器
ProductController
[ApiController]
[Route("Product")]
public class ProductController : ControllerBase
{
private readonly ILogger<ProductController> _logger;
private readonly IProductService _productService;
public ProductController(ILogger<ProductController> logger, IProductService productService)
{
_logger = logger;
_productService = productService;
}
/// <summary>
/// 查询商品
/// </summary>
/// <returns></returns>
[HttpGet]
public ActionResult<IEnumerable<Product>> GetProducts()
{
return _productService.GetProducts().ToList();
}
/// <summary>
/// 查询商品
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpGet("{id}")]
public ActionResult<Product> GetProduct(string id)
{
var product = _productService.GetProductById(id);
if (product == null)
{
return NotFound();
}
return product;
}
/// <summary>
/// 查询商品(分页查询)
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpGet("ProductsPage")]
public ActionResult<IEnumerable<Product>> GetProductsByPage(int page, int pageSize)
{
var products = _productService.GetProductsByPage(page, pageSize).ToList();
if (products == null)
{
return NotFound();
}
return products;
}
/// <summary>
/// 字段查询
/// </summary>
/// <param name="productDto"></param>
/// <returns></returns>
[HttpGet("KeywordSearch")]
public ActionResult<IEnumerable<Product>> GetProductsKeywordSearch([FromQuery]ProductDto productDto)
{
var products = _productService.GetProductsKeywordSearch(productDto);
if (products == null)
{
return NotFound();
}
return products.ToList();
}
/// <summary>
/// 全文搜索
/// </summary>
/// <param name="productDto"></param>
/// <returns></returns>
[HttpGet("TextSearch")]
public ActionResult<IEnumerable<Product>> GetProductsTextSearch([FromQuery] ProductDto productDto)
{
var products = _productService.GetProductsTextSearch(productDto);
if (products == null)
{
return NotFound();
}
return products.ToList();
}
/// <summary>
/// 聚合查询
/// </summary>
/// <param name="productDto"></param>
/// <returns></returns>
[HttpGet("AggreateTextSearch")]
public ActionResult<ValueAggregate> GetProductsAggreateTextSearch([FromQuery] ProductDto productDto)
{
var products = _productService.GetProductsAggreateTextSearch(productDto);
if (products == null)
{
return NotFound();
}
return products;
}
/// <summary>
/// 添加商品
/// </summary>
/// <param name="product"></param>
/// <returns></returns>
[HttpPost]
public ActionResult<Product> PostProduct(Product product)
{
_productService.Create(product);
return CreatedAtAction("GetProduct", new { id = product.Id }, product);
}
/// <summary>
/// 修改商品
/// </summary>
/// <param name="id"></param>
/// <param name="product"></param>
/// <returns></returns>
[HttpPut("{id}")]
public IActionResult PutProduct(string id, Product product)
{
if (id != product.Id)
{
return BadRequest();
}
try
{
_productService.Update(product);
}
catch (Exception)
{
throw;
}
return NoContent();
}
/// <summary>
/// 删除商品
/// </summary>
/// <param name="id"></param>
/// <param name="product"></param>
/// <returns></returns>
[HttpDelete("{id}")]
public IActionResult DeleteProduct(string id)
{
try
{
_productService.Delete(id);
}
catch (Exception)
{
throw;
}
return NoContent();
}
}
3.CRUD封装
/// <summary>
/// 商品服务接口
/// </summary>
public interface IProductService
{
IEnumerable<Product> GetProducts();
IEnumerable<Product> GetProductsByPage(int page, int pageSize);
IEnumerable<Product> GetProducts(List<string> ids);
/// <summary>
/// 全文搜索(keyword查询)
/// </summary>
/// <returns></returns>
IEnumerable<Product> GetProductsKeywordSearch(ProductDto productDto);
/// <summary>
/// 全文搜索(text查询)
/// </summary>
/// <returns></returns>
IEnumerable<Product> GetProductsTextSearch(ProductDto productDto);
/// <summary>
/// 全文搜索(text范围查询)
/// </summary>
/// <returns></returns>
IEnumerable<Product> GetProductsRangeTextSearch(ProductDto productDto);
/// <summary>
/// 全文搜索(text聚合查询)
/// </summary>
/// <returns></returns>
ValueAggregate GetProductsAggreateTextSearch(ProductDto productDto);
/// <summary>
/// 全文搜索(text查询)---(排序)
/// </summary>
/// <returns></returns>
IEnumerable<Product> GetProductsTextSearchSort(ProductDto productDto);
/// <summary>
/// 全文搜索(MutilText查询)
/// </summary>
/// <returns></returns>
IEnumerable<Product> GetProductsMutilTextSearch(ProductDto productDto);
/// <summary>
/// 全文搜索(嵌套文档查询)
/// </summary>
/// <returns></returns>
IEnumerable<Product> GetProductsNestedTextSearch(ProductDto productDto);
/// <summary>
/// 全文搜索(扩展(地理位置查询和IP查询))
/// </summary>
/// <returns></returns>
IEnumerable<Product> GetProductsIPTextSearch(ProductDto productDto);
Product GetProductById(string id);
void Create(Product Product);
void CreateList(List<Product> Products);
void Update(Product Product);
void UpdateList(List<Product> Products);
void Delete(string Id);
void Deletelist(List<Product> Products);
bool ProductExists(int id);
}
public class ProductService : IProductService
{
private readonly ElasticClient elasticClient;
public ProductService(/*IConfiguration configuration*/IOptions<ProductMongoDBOptions> options)
{
/* ProductMongoDBOptions productMongoDBOptions = options.Value;
// 1、建立MongoDB连接
var client = new MongoClient(productMongoDBOptions.ConnectionString);
// 2、获取商品库
var database = client.GetDatabase("productdb");
// 3、获取商品表(集合)
_products = database.GetCollection<Product>("Product");*/
#region 1、单实例连接
{
/* var node = new Uri("http://localhost:9200");
// var defaultIndex = "products";
var settings = new ConnectionSettings(node);
//.DefaultIndex(defaultIndex);
elasticClient = new ElasticClient(settings);*/
}
#endregion
#region 2、集群连接
{
var nodes = new Uri[]
{
new Uri("http://localhost:9201"),
new Uri("http://localhost:9202"),
new Uri("http://localhost:9203"),
};
var pool = new StaticConnectionPool(nodes);
var settings = new ConnectionSettings(pool);
elasticClient = new ElasticClient(settings);
}
#endregion
}
public void Create(Product Product)
{
elasticClient.Index(Product,idx => idx.Index("products_cluster")); // 创建数据库
}
public void CreateList(List<Product> Products)
{
elasticClient.IndexMany<Product>(Products, "products");
}
public void Delete(string Id)
{
elasticClient.Delete<Product>(Id, idx => idx.Index("products"));
}
public void Deletelist(List<Product> Products)
{
elasticClient.DeleteMany<Product>(Products, "products");
}
public Product GetProductById(string id)
{
return elasticClient.Get<Product>(id, idx => idx.Index("products")).Source;
}
public IEnumerable<Product> GetProducts()
{
#region 1、直接查询
{
var request = new SearchRequest("products");
var dems = elasticClient.Search<Product>(request);
return dems.Documents;
}
#endregion
#region 2、委托查询
{
return elasticClient.Search<Product>(s => s
.Index("products")
).Documents;
}
#endregion
}
public IEnumerable<Product> GetProductsByPage(int page, int pageSize)
{
#region 1、直接查询
{
var request = new SearchRequest("products");
request.From = (page-1)* pageSize;
request.Size = pageSize;
return elasticClient.Search<Product>(request).Documents;
}
#endregion
#region 2、委托查询
{
return elasticClient.Search<Product>(s => s
.Index("products")
.From((page - 1) * pageSize)
.Size(pageSize)
).Documents;
}
#endregion
}
public IEnumerable<Product> GetProducts(List<string> ids)
{
List<Product> products = new List<Product>();
var response = elasticClient.GetMany<Product>(ids, "products");
foreach (var multiGetHit in response)
{
if (multiGetHit.Found)
{
products.Add(multiGetHit.Source);
}
}
return products;
}
public IEnumerable<Product> GetProductsKeywordSearch(ProductDto productDto)
{
return elasticClient.Search<Product>(s => s
.Index("products_cluster")
.Query(q => q
.Match( mq => mq.Field(f => f.ProductTitle).Query(productDto.ProductTitle))
)
).Documents;
}
public IEnumerable<Product> GetProductsTextSearch(ProductDto productDto)
{
#region 1、单文本查询
{
return elasticClient.Search<Product>(s => s
.Index("products")
.Query(q => q
.Term(t => t.ProductTitle, productDto.ProductTitle)
)
).Documents;
}
#endregion
}
public IEnumerable<Product> GetProductsRangeTextSearch(ProductDto productDto)
{
#region 1、单文本范围查询
{
return elasticClient.Search<Product>(s => s
.Index("products")
.Query(q => q
.TermRange(tr => tr.Field(f => f.ProductPrice).GreaterThanOrEquals("19.00").LessThan("100.00"))
)
).Documents;
}
#endregion
}
public ValueAggregate GetProductsAggreateTextSearch(ProductDto productDto)
{
#region 1、聚合查询(平均值)
{
var ducmentsss = elasticClient.Search<Product>(s => s
.Index("products")
.Query(q => q.Match(mq => mq.Field(f => f.ProductTitle).Query(productDto.ProductTitle)))
.Aggregations(a => a.Average("ProductPrice_Average", aa => aa.Field(f => f.ProductPrice)))
.Aggregations(a => a.Min("ProductPrice_Min", aa => aa.Field(f => f.ProductPrice)))
.Aggregations(a => a.Max("ProductPrice_Max", aa => aa.Field(f => f.ProductPrice)))
.Aggregations(a => a.Sum("ProductPrice_Sum", aa => aa.Field(f => f.ProductPrice)))
).Aggregations.Min("ProductPrice_Max");
return ducmentsss;
}
#endregion
#region 2、聚合查询(求和)
{
/*return elasticClient.Search<Product>(s => s
.Index("products")
.Query(q => q
.Term(t => t.ProductTitle, productDto.ProductTitle)
).Aggregations(a => a
.Sum("ProductPrice_Sum", aa => aa.Field(f => f.ProductPrice))
)
).Aggregations.Sum("ProductPrice_Sum");*/
}
#endregion
#region 3、聚合查询(最小值)
{
/*return elasticClient.Search<Product>(s => s
.Index("products")
.Query(q => q
.Term(t => t.ProductTitle, productDto.ProductTitle)
).Aggregations(a => a
.Min("ProductPrice_Min", aa => aa.Field(f => f.ProductPrice))
)
).Aggregations.Min("ProductPrice_Min");*/
}
#endregion
#region 4、聚合查询(最大值)
{
/*return elasticClient.Search<Product>(s => s
.Index("products")
.Query(q => q
.Term(t => t.ProductTitle, productDto.ProductTitle)
).Aggregations(a => a
.Max("ProductPrice_Max", aa => aa.Field(f => f.ProductPrice))
)
).Aggregations.Max("ProductPrice_Max");*/
}
#endregion
#region 5、聚合查询(百分数)
{
var test = elasticClient.Search<Product>(s => s
.Index("products")
.Query(q => q
.Term(t => t.ProductTitle, productDto.ProductTitle)
).Aggregations(a => a
.Percentiles("ProductPrice_Percentiles", aa => aa.Field(f => f.ProductPrice))
)
).Aggregations.Percentiles("ProductPrice_Percentiles");
return null;
}
#endregion
}
public IEnumerable<Product> GetProductsTextSearchSort(ProductDto productDto)
{
#region 1、文本查询(升序排序)
{
return elasticClient.Search<Product>(s => s
.Index("products")
.Query(q => q
.Term(t => t.ProductTitle, productDto.ProductTitle)
).Sort(s => s.Ascending(a => a.Id))
).Documents;
}
#endregion
#region 1、文本查询(降序序排序)
{
return elasticClient.Search<Product>(s => s
.Index("products")
.Query(q => q
.Term(t => t.ProductTitle, productDto.ProductTitle)
).Sort(s => s.Descending(a => a.Id))
).Documents;
}
#endregion
}
public IEnumerable<Product> GetProductsMutilTextSearch(ProductDto productDto)
{
#region 1、多文本 ||查询
{
return elasticClient.Search<Product>(s => s
.Index("products")
.Query(q => q
.Term(t => t.ProductTitle, "tony") || q
.Term(t => t.ProductDescription,"text")
)
).Documents;
}
#endregion
#region 2、多文本 && 查询
{
return elasticClient.Search<Product>(s => s
.Index("products")
.Query(q => q
.Term(t => t.ProductTitle, "tony") && q
.Term(t => t.ProductDescription, "text")
)
).Documents;
}
#endregion
}
public IEnumerable<Product> GetProductsNestedTextSearch(ProductDto productDto)
{
#region 1、对象嵌套查询
{
return elasticClient.Search<Product>(s => s
.Index("products")
.Query(q => q
//.Term(t => t.ProductDescription, "tony")
/*.Nested(n => n
.Path(p => p.productSales)
.Query(q => q
.Term(m => m
.Field( f => f.productSales.SoldCount)
.Value("2")
)
)
)*/
)).Documents;
}
#endregion
#region 2、数组嵌套查询
{
return elasticClient.Search<Product>(s => s
.Index("products")
.Query(q => q
//.Term(t => t.ProductDescription, "tony")
/*.Nested(n => n
.Path( p => p.productImages)
.Query( q => q
.Match( m => m
.Field(f => f.productImages[0].ImageStatus)
.Query("1")
)
)
)*/
)).Documents;
}
#endregion
}
public void Update(Product Product)
{
elasticClient.Update<Product>(Product.Id, idx =>
idx.Upsert(Product).Index("products")
);
}
public void UpdateList(List<Product> Products)
{
// elasticClient.PutScript
// elasticClient.SearchShards
// elasticClient.UpdateByQuery
}
public bool ProductExists(int id)
{
return elasticClient.DocumentExists<Product>(id, idx =>idx.Index("products")).Exists;
}
public IEnumerable<Product> GetProductsIPTextSearch(ProductDto productDto)
{
throw new NotImplementedException();
}
}
三、扩展
以下是Elasticsearch中crud写法,不过目前Elasticsearch支持sql写法以下适用于老版本
1.索引操作
1.1 创建索引
创建索引yg
PUT /yg
{
"settings": {
"index": {
"number_of_shards": 1,
"number_of_replicas": 0
}
}
}
- number_of_shards是主分片数。
- number_of_replicas是一个主分片有多少个本。
那么总的分片数就是(number_of_replicas + 1) * number_of_shards
1.2 查看索引
GET /yg/
1.3 删除索引
DELETE /yg/
2.文档操作
2.1 插入文档
自动生成_id
POST /yg/_doc
{
"title": "The Pursuit of Happyness",
"actors": [
"Will Smith",
"Jaden Smith",
"Thandie Newton"
]
}
指定_id=1
PUT /yg/_doc/1
{
"title": "The Pursuit of Happyness",
"actors": [
"Will Smith",
"Jaden Smith",
"Thandie Newton"
]
}
覆盖文档
PUT /yg/_doc/1
{
"title": "xxx"
}
如果是指定_id
的情况下文档已经存在的话,会直接进行覆盖,如果里面有些字段没传,那个字段就不会存储了,比如上面的覆盖文档,执行完后去获取_id=1
的数据,只能获取到title
字段,actors
字段是不存在的。
2.2 更新文档
POST /yg/_update/1
{
"doc":{
"title": "The Pursuit of Happyness xxx"
}
}
更新_id=1
的数据,注意需要有doc
。如果用POST /yg/_update/1
这种语法,就直接覆盖了。
2.3 删除文档
删除_id=1
的数据
DELETE /yg/_doc/1
2.4 获取文档
获取_id=1
的数据
GET /yg/_doc/1
2.5 搜索文档
GET /ygs/_search
{
"profile": "true",
"_source": ["movieId", "title","genres"],
"sort": [{"movieId": "desc"}],
"from": 0,
"size": 3,
"query": {
"match_all": {}
}
}
上面翻译成sql语句是
select movieId, title, genres from ygs order by movieId desc limit 0, 3
- ygs是之前导入的数据,非前面用的yg,需要测试的话要先导入一下数据。
- profile 相当于MySQL中的explain
- _source 是要返回的字段
3.文档数据操作
3.1 文档数据更新
{"index":{"_index":"yg","_id":1}}
{"title": "xxx xx"}
{"index":{"_index":"yg","_id":2}}
{"title": "The Pursuit of Happyness"}
{"update":{"_index":"yg","_id":2}}
{"doc":{"title": "xxx xx"}}
3.2 文档数据读取
GET _mget
{
"docs": [
{
"_index": "yg",
"_id": 1
},
{
"_index": "yg",
"_id": 2
}
]
}
如果是对同一个index进行操作,可以在URI指定index
GET yg/_mget
{
"docs": [
{
"_id": 1
},
{
"_id": 2
}
]
3.3 文档数据查询
GET /movies/_msearch
{}
{"from":0,"size":1,"query":{"match_all":{}}}
{}
{"from":0,"size":2,"query":{"match_all":{}}}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)