首页 > 其他分享 >.Net Core8下Elasticsearch7.x+Nest升级到Elasticsearch8.x+Elastic.Clients.Elasticsearch分享

.Net Core8下Elasticsearch7.x+Nest升级到Elasticsearch8.x+Elastic.Clients.Elasticsearch分享

时间:2024-06-23 21:33:10浏览次数:20  
标签:return Elastic OutPutResult Nest Clients ex var new resp

背景

Elasticsearch升级到8.11了,对应的客户端插件也跟着升级,以为会兼容Nest的语法,发现自己Too Young Too Simple!
没办法,只能去官网找,结果官网只有最基本的增、删、改、查,只能继续查资料,发现网上资料很少,避免大家少走弯路,这里做个简单的分享。

分享

1.ElasticsearchClient

var esSetting = _baseConfig.Es;
if (esSetting == null || string.IsNullOrEmpty(esSetting.EsHosts))
{
    throw new Exception("未配置EsHosts");
}

//读取ES集群配置
var nodeUris = GetAllNodes(esSetting);

services.AddSingleton<ElasticsearchClient>(provider =>
{
    //这里用的StaticNodePool,单节点和集群都支持,大家根据自己实际情况选择
    var pool = new StaticNodePool(nodeUris);
    var settings = new ElasticsearchClientSettings(pool);
    //如果设置了账号密码
    if (!string.IsNullOrEmpty(esSetting.EsUser) && !string.IsNullOrEmpty(esSetting.EsPassword))
    {
        settings.Authentication(new BasicAuthentication(esSetting.EsUser, esSetting.EsPassword));
    }
    return new ElasticsearchClient(settings);
});

return services;
//settings.EsHosts示例:http://192.168.1.100:9200;http://192.168.1.101:9200;http://192.168.1.102:9200
private static List<Uri> GetAllNodes(EsConfig settings)
{
    var nodes = settings.EsHosts.Trim();
    string[] nodeshost = nodes.Split(';');
    var nodUris = new List<Uri>();
    for (int i = 0; i < nodeshost.Length; i++)
    {
        if (!string.IsNullOrEmpty(nodeshost[i]))
            nodUris.Add(new Uri(nodeshost[i]));
    }
    return nodUris;
}

2.具体使用

2.1注入_client

public class ElasticSearchForInformalEssay : IElasticSearchForInformalEssay
{
    private readonly string IndexName = "informal_essay_info";

    private readonly ILogger<ElasticSearchForInformalEssay> _logger;
    protected ElasticsearchClient _client { get; set; }
    public ElasticSearchForInformalEssay(ILogger<ElasticSearchForInformalEssay> logger, ElasticsearchClient client)
    {
        _logger = logger;
        _client = client;
    }
}

2.2增加-增加跟Nest版本基本一致

/// <summary>
/// 添加单条数据
/// </summary>
/// <param name="InformalEssay"></param>
/// <returns></returns>
public OutPutResult AddIndex(informal_essay_info InformalEssay)
{
    try
    {
        var resp = _client.Index<informal_essay_info>(InformalEssay, x => x.Index(IndexName));

        if (resp.IsValidResponse)
        {
            return OutPutResult.ok();
        }
        else
        {
            return OutPutResult.error(resp.DebugInformation);
        }

    }
    catch (Exception ex)
    {
        return OutPutResult.error(ex.Message);
    }
}

/// <summary>
/// 添加多条数据
/// </summary>
/// <param name="InformalEssays"></param>
/// <returns></returns>
public OutPutResult BulkAddIndex(List<informal_essay_info> InformalEssays)
{
    try
    {
        //var resp = _client.BulkAll<informal_essay_info>(InformalEssays, x => x.Index(IndexName).Size(1000));

        var observableBulk = _client.BulkAll(InformalEssays, f => f
                .MaxDegreeOfParallelism(8)
                .BackOffTime(TimeSpan.FromSeconds(10))
                .BackOffRetries(2)
                .Size(1000)
                .RefreshOnCompleted()
                .Index(IndexName)
                .BufferToBulk((r, buffer) => r.IndexMany(buffer))
            );
        var countdownEvent = new CountdownEvent(1);
        var bulkAllObserver = new BulkAllObserver(
        onNext: response =>
        {
            //_logger.LogInformation($"索引 {response.Page} 页,每页1000条,重试 {response.Retries} 次");
        },
        one rror: ex =>
        {
            _logger.LogInformation("添加索引异常 : {0}", ex);
            countdownEvent.Signal();
        },
        () =>
        {
            _logger.LogInformation("添加索引完成");
            countdownEvent.Signal();
        });

        observableBulk.Subscribe(bulkAllObserver);


        //var resp = _client.IndexMany(InformalEssays, IndexName);
        return OutPutResult.ok();

    }
    catch (Exception ex)
    {
        _logger.LogInformation("批量操作异常:", ex);
        return OutPutResult.error(ex.Message);
    }
}

2.3删除

/// <summary>
/// Id单条删除
/// </summary>
/// <param name="InformalEssayId"></param>
/// <returns></returns>
public OutPutResult DeleteById(string InformalEssayId)
{
    try
    {
        var resp = _client.Delete<informal_essay_info>(InformalEssayId, x => x.Index(IndexName));

        if (resp.IsValidResponse)
        {
            return OutPutResult.ok();
        }
        else
        {
            return OutPutResult.error(resp.DebugInformation);
        }

    }
    catch (Exception ex)
    {
        return OutPutResult.error(ex.Message);
    }
}

/// <summary>
/// Ids批量删除
/// </summary>
/// <param name="InformalEssayIds"></param>
/// <returns></returns>
public OutPutResult BulkDeleteById(string InformalEssayIds)
{
    try
    {
        var ids = CommonHelpers.GetStringArray(InformalEssayIds).ToList();

        List<FieldValue> terms = new();

        ids.ForEach(x =>
        {
            terms.Add(x);
        });

        var resp = _client.DeleteByQuery<informal_essay_info>(IndexName, x => x.
        Query(q => q.Terms(t => t.Field(f => f.id).Terms(new TermsQueryField(terms))))
        .Refresh(true)
        );

        if (resp.IsValidResponse)
        {
            return OutPutResult.ok();
        }
        else
        {
            return OutPutResult.error(resp.DebugInformation);
        }

    }
    catch (Exception ex)
    {
        return OutPutResult.error(ex.Message);
    }
}

/// <summary>
/// 根据条件批量删除
/// </summary>
/// <param name="keyword"></param>
/// <param name="start"></param>
/// <param name="end"></param>
/// <returns></returns>
public OutPutResult BulkDeleteByQuery(string keyword, DateTime? start, DateTime? end)
{
    try
    {
        var mustQueries = new List<Action<QueryDescriptor<informal_essay_info>>>();

        if (start.HasValue || end.HasValue)
        {
            long startDate = CommonHelpers.DateTimeToTimeStamp(start ?? DateTime.MinValue);
            long endDate = CommonHelpers.DateTimeToTimeStamp(end ?? DateTime.MaxValue);

            mustQueries.Add(t => t.Range(r => r.NumberRange(n => n.Field(f => f.setdate).Gte(startDate).Lte(endDate))));
        }

        if (!string.IsNullOrEmpty(keyword))
        {
            mustQueries.Add(t => t.MultiMatch(m => m.Fields(
                new Field("title", 10).And(new Field("content", 5)).And(new Field("author", 5))
                ).Operator(Operator.And).Query(keyword)));
        }

        Action<QueryDescriptor<informal_essay_info>> retQuery = q => q.Bool(b => b.Filter(mustQueries.ToArray()));

        var resp = _client.DeleteByQuery<informal_essay_info>(IndexName, s => s
           .Query(q => q.Bool(b => b.Must(retQuery)))
       );

        if (resp.IsValidResponse)
        {
            return OutPutResult.ok();
        }
        else
        {
            return OutPutResult.error(resp.DebugInformation);
        }

    }
    catch (Exception ex)
    {
        return OutPutResult.error(ex.Message);
    }
}

2.4修改

public OutPutResult UpdateIndex(informal_essay_info InformalEssay)
{
    try
    {
        var resp = _client.Index<informal_essay_info>(InformalEssay, x => x.Index(IndexName).Refresh(Refresh.True));
        if (resp.IsValidResponse)
        {
            return OutPutResult.ok();
        }
        else
        {
            return OutPutResult.error(resp.DebugInformation);
        }

    }
    catch (Exception ex)
    {
        return OutPutResult.error(ex.Message);
    }
}

/// <summary>
/// 批量修改
/// </summary>
/// <param name="InformalEssays"></param>
/// <returns></returns>
public OutPutResult BulkUpdateIndex(List<informal_essay_info> InformalEssays)
{
    try
    {
        var observableBulk = _client.BulkAll(InformalEssays, f => f
                .MaxDegreeOfParallelism(8)
                .BackOffTime(TimeSpan.FromSeconds(10))
                .BackOffRetries(2)
                .Size(1000)
                .RefreshOnCompleted()
                .Index(IndexName)
                .BufferToBulk((r, buffer) => r.IndexMany(buffer))
            );

        var bulkAllObserver = new BulkAllObserver(
        onNext: response =>
        {
            _logger.LogInformation($"索引 {response.Page} 页,每页1000条,重试 {response.Retries} 次");
        },
        one rror: ex =>
        {
            _logger.LogInformation("更新索引异常 : {0}", ex);
        },
        () =>
        {
            _logger.LogInformation("完成更新索引");
        });

        observableBulk.Subscribe(bulkAllObserver);

        return OutPutResult.ok();
    }
    catch (Exception ex)
    {
        return OutPutResult.error(ex.Message);
    }
}

/// <summary>
/// 根据条件修改(稿件发布/取消发布后,更新ES)
/// </summary>
/// <param name="id"></param>
/// <param name="status">1:发布,0:取消发布,-1:删除</param>
/// <returns></returns>
public OutPutResult UpdateInformalEssayInfoAfterPublishOrCancel(string id, int status = 1)
{
    try
    {
        var sql = $"ctx._source.status = params.status;";

        var scriptParams = new Dictionary<string, object> { { "status", status } };
        var req = new UpdateByQueryRequest(IndexName)
        {
            Query = new TermQuery("id") { Field = "id", Value = id },
            Script = new Script(new InlineScript() { Source = sql, Params = scriptParams }),
            Refresh = true
        };

        var resp = _client.UpdateByQuery(req);

        if (resp.IsValidResponse)
        {
            return OutPutResult.ok();
        }
        else
        {
            return OutPutResult.error(resp.DebugInformation);
        }

    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "稿件发布/取消发布后,更新ES:");
        return OutPutResult.error("稿件发布/取消发布后,更新ES:" + ex.Message);
    }
}

2.5查询

/// <summary>
/// id单条查询
/// </summary>
/// <param name="InformalEssayId"></param>
/// <returns></returns>
public OutPutResult SerachById(string InformalEssayId)
{
    try
    {
        var search = _client.Get<informal_essay_info>(InformalEssayId, s => s.Index(IndexName));

        var data = search.Source;

        return OutPutResult.ok().put("data", data);

    }
    catch (Exception ex)
    {
        return OutPutResult.error(ex.Message);
    }
}

/// <summary>
/// ids多条查询
/// </summary>
/// <param name="InformalEssayIds"></param>
/// <returns></returns>
public OutPutResult SerachByIds(string InformalEssayIds)
{
    try
    {
        var ids = CommonHelpers.GetStringArray(InformalEssayIds).ToList();
        List<FieldValue> terms = new();

        ids.ForEach(x =>
        {
            terms.Add(x);
        });
        var search = _client.Search<informal_essay_info>(s => s.Index(IndexName).Query(
            q => q.Terms(t => t.Field(f => f.id).Terms(new TermsQueryField(terms)))
            ));

        var data = search.Documents.ToList();

        return OutPutResult.ok().put("data", data);

    }
    catch (Exception ex)
    {
        return OutPutResult.error(ex.Message);
    }
}


/// <summary>
/// 列表分页查询
///(不要说深度分页性能问题,用户说不用管,哈哈,就要全部查出来,慢点没关系)
/// 其实尝试过几种方案,具体使用人员就觉得直接分页最方便,最后直接max_result_window设置了1千万
/// (用户800万左右的数据,三台16核32GB的服务器部署的ES集群+Redis集群,深度分页1秒多,完全能接受)
/// </summary>
/// <param name="category"></param>
/// <param name="keyword"></param>
/// <param name="start"></param>
/// <param name="end"></param>
/// <param name="pageindex"></param>
/// <param name="rows"></param>
/// <param name="orderField"></param>
/// <param name="order"></param>
/// <returns></returns>
public OutPutResult SerachInformalEssays(string category, string keyword, DateTime? start, DateTime? end, int pageindex = 1, int rows = 20, int string orderField = "setdate", SortOrder order = SortOrder.Desc)
{
    try
    {
        var mustQueries = new List<Action<QueryDescriptor<informal_essay_info>>>();

        //状态,0为正常,-1为删除,1为发布
        mustQueries.Add(t => t.Term(f => f.status, 1));

        if (!string.IsNullOrEmpty(category))
        {
            mustQueries.Add(t => t.MatchPhrase(f => f.Field(fd => fd.category).Query(category)));
        }

        if (!string.IsNullOrEmpty(keyword))
        {
            mustQueries.Add(t => t.MultiMatch(m => m.Fields(
                new Field("title", 10).And(new Field("content", 5)).And(new Field("author", 5)).And(new Field("keyword", 5))
                ).Operator(Operator.And).Query(keyword)));

        }

        if (start.HasValue || end.HasValue)
        {
            long startDate = CommonHelpers.DateTimeToTimeStamp(start ?? DateTime.MinValue);
            long endDate = 0;
            if (end != null && end.HasValue)
            {
                string endtime = string.Format("{0:d}", end) + " 23:59:59";
                end = Convert.ToDateTime(endtime);
                endDate = CommonHelpers.DateTimeToTimeStamp(end ?? DateTime.MaxValue);
            }
            else
            {
                endDate = CommonHelpers.DateTimeToTimeStamp(end ?? DateTime.MaxValue);
            }

            mustQueries.Add(t => t.Range(r => r.NumberRange(n => n.Field("setdate").Gte(startDate).Lte(endDate))));
        }

        var search = _client.Search<informal_essay_info>(s => s
             .Index(IndexName)
             .Query(q => q.Bool(b => b.Must(mustQueries.ToArray())))
             .From((pageindex - 1) * rows)
             .Size(rows)
             .Sort(s => s.Field(orderField, new FieldSort { Order = order }))
         );
        return OutPutResult.ok().put("total", search.Total).put("data", search.Documents);

    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "查询随笔异常:");
        return OutPutResult.error(ex.Message);
    }
}

标签:return,Elastic,OutPutResult,Nest,Clients,ex,var,new,resp
From: https://www.cnblogs.com/libian/p/18254894

相关文章

  • elasticsearch 全文搜素 query_string 搭配其他条件
    elasticsearch全文搜素query_string搭配其他条件{"query":{"bool":{"must":[{"term":{"item_type":"question"......
  • 实战教你ElasticSearch-8.13集群搭建
    elasticsearch8.13集群部署elasticsearch8.13analysis-ikelastiknn环境准备(每台节点都需要修改)修改系统参数-----https://www.elastic.co/guide/en/elasticsearch/reference/current/system-config.html(官方推荐)#vim/etc/security/limits.conf新增内容如下:*har......
  • 【微服务】第24节:初识搜索引擎 ElasticSearch
    目录1.初识elasticsearch1.1.认识和安装1.1.1.安装elasticsearch1.1.2.安装Kibana1.2.倒排索引1.2.1.正向索引1.2.2.倒排索引1.2.3.正向和倒排1.3.基础概念1.3.1.文档和字段1.3.2.索引和映射1.3.3.mysql与elasticsearch1.4.IK分词器1.4.1.安装IK分词器1.4.2.使......
  • elasticsearch-7.17.15 集群安装部署及kibana配置
    一、物料准备(注意:必须版本一致):1、安装包 elasticsearch-7.17.15-linux-x86_64.tar.gz(这个版本的插件需要在线使用命令安装:/es/elasticsearch-7.17.15/bin/elasticsearch-plugininstallhttps://get.infini.cloud/elasticsearch/analysis-ik/7.17.15,或者用我的传送门) an......
  • Elasticsearch
    Elasticsearch(ES),这是一个开源的搜索和分析引擎,广泛用于各种应用中以实现全文搜索、结构化搜索、分析和复杂的数据查询。下面我将详细介绍Elasticsearch的基本概念、架构和工作原理。Elasticsearch的基本概念节点(Node)Elasticsearch运行的单个实例称为节点。每个节点都存储数据,并......
  • 【异常】nested exception is java.lang.NoClassDefFoundError: redis/clients/jedis/
    原因是版本冲突。以下我原本使用的版本信息<!--SpringBootRedis依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><version>2.1.8.RELEASE</version><......
  • ElasticSearch入门(实战)
    环境准备:VMwaredocker   创建一个linux虚拟机,使用dockerpullelasticsearch 部署单体服务: dockerpullelasticsearch:6.8.13#elasticsearch十分占用内存,用这种方式启动会导致Linux卡机dockerrun-d--nameelasticsearch-p9200:9200-p9300:9300-e"discover......
  • 安装elastic-view
    1.基于二进制包部署ElasticView1、下载并解压#下载wgethttps://github.com/1340691923/ElasticView/releases/download/v1.8.7/ElasticViewLinux.zip#解压mkdir-p/opt/ElasticViewunzip/usr/local/src/ElasticViewLinux.zip-d/opt/ElasticViewmv/opt/ElasticVi......
  • 【2024最新精简版】ElasticSearch面试篇
    文章目录你们项目中主要使用ElasticSearch干什么什么是正向索引?什么是倒排索引?......
  • Elasticsearch如何聚合查询多个统计值,如何嵌套聚合?并相互引用,统计索引中某一个字段的
    目录Elasticsearch聚合查询说明空值率查询DSLElasticsearch聚合基础知识扩展Elasticsearch聚合概念Script用法Elasticsearch聚合查询语法指标聚合(MetricAggregations)桶聚合(BucketAggregations)矩阵聚合(MatrixAggregations)组合聚合(PipelineAggregations)Elasticsearch聚合查询......