首页 > 其他分享 >使用NEST简单操作Elasticsearch

使用NEST简单操作Elasticsearch

时间:2023-05-16 10:35:25浏览次数:43  
标签:await indexName NEST 简单 fd Elasticsearch esClient var new

.Net Core中使用NEST简单操作Elasticsearch

 

C#中访问Elasticsearch主要通过两个包NESTElasticsearch.NetNEST用高级语法糖封装了Elasticsearch.Net可以通过类Linq的方式进行操作,而Elasticsearch.Net相比之下更为原始直接非常自由。

注意:ES8.X以上的版本有新的包Elastic.Clients.Elasticsearc支持。

此处使用NEST,我们通过Nuget安装,如下图:

1、准备结构

 准备以下实体

复制代码
public class Company
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public User User { get; set; }
    }
    public class User
    {
        public string Name { get; set; }
        public int Gender { get; set; }
    }
复制代码

2、连接ES

 如果是单机连接如下代码,可以直接在Uri上指定账号密码,也可以使用ConnectionSettingsBasicAuthentication来配置账号密码:

var singleNode = new Uri("http://elastic:123456@localhost:9200");
    var connSettings = new ConnectionSettings(singleNode);
  //connSettings.BasicAuthentication("elastic", "123456"); var esClient = new ElasticClient(connSettings);

如果是多个节点集群则如下代码:

复制代码
var nodes = new Uri[]
    {
        new Uri("http://esNode1:9200"),
        new Uri("http://esNode2:9200"),
        new Uri("http://esNode3:9200")
    };
    var pool = new StaticConnectionPool(nodes);
    var settings = new ConnectionSettings(pool);
    var client = new ElasticClient(settings);
复制代码

3、创建索引

索引名称必须符合规则否则创建会失败,比如索引只能小写,具体代码如下:

var indexName = "my_index1";//索引名称
    var res = await esClient.Indices.CreateAsync(indexName, o => o.Map(g => g.AutoMap<Company>()));//映射结构

 也可以在向索引插入数据的时候自动判断是否存在索引,不存在会自动创建。索引结构字段映射一但创建就无法修改,可以通过新建索引然后转移数据的方式修改索引结构,但是可以往里面新增字段映射,比如修改了实体结构新的字段将会被映射。

4、插入数据

使用IndexDocumentAsync方法插入单条数据需要在ConnectionSettingsDefaultIndex方法设置默认索引。使用IndexAsync插入单条数据时需要选择指定索引,如下:

复制代码
var singleNode = new Uri("http://localhost:9200");
    var connSettings = new ConnectionSettings(singleNode);
    connSettings.BasicAuthentication("elastic", "123456");
    var esClient = new ElasticClient(connSettings.DefaultIndex("my_index1"));
    var indexName = "my_index1";
    var company = new Company()
    {
        Name = "超级公司bulk",
        Description = "超级描述bulk",
    };
    var res1 = await esClient.IndexDocumentAsync(company);
    var res2 = await esClient.IndexAsync(company, g => g.Index(indexName))    
复制代码

 如果需要批量插入需要用BulkDescriptor对象包裹,然后使用BulkAsync方法插入,或者不要包裹直接用IndexManyAsync方法插入,具体如下:

复制代码
var company = new Company()
    {
        Name = "超级公司bulk",
        Description = "超级描述bulk"
    });
    BulkDescriptor descriptor = new BulkDescriptor();
    descriptor.Index<Company>(op => op.Document(company).Index(indexName));
    var res = await esClient.BulkAsync(descriptor);
    //var list = new List<Company>();
    //list.Add(company);
    //var res = await esClient.IndexManyAsync(list, indexName);  
复制代码

 如果实体有Id则会使用Id的值做为_id的索引文档唯一值,或者可以通过手动指定如await esClient.IndexAsync(company, g => g.Index(indexName).Id(company.Id)),如果id相同执行插入操作则为更新不会重复插入。在新增后是会返回id等信息可以加以利用。

5、删除数据

删除指定单条数据需要知道数据的id,如下两种方式:

DocumentPath<Company> deletePath = new DocumentPath<Company>(Guid.Empty);
    var delRes = await esClient.DeleteAsync(deletePath, g => g.Index(indexName));
    //或者
    IDeleteRequest request = new DeleteRequest(indexName, "1231");
    var delRes = await esClient.DeleteAsync(request);

 多条删除使用DeleteByQueryAsync方法进行匹配删除,下面两种方式等价,删除Description字段模糊查询有描述的数据(最多10条):

复制代码
var req = new DeleteByQueryRequest<Company>(indexName)
    {
        MaximumDocuments = 10,//一次最多删几条
        Query = new MatchQuery()
                {
                    Field = "description",
                    Query = "描述"
                }
    };
    var result = await esClient.DeleteByQueryAsync(req);
    //等价于
    var result = await esClient.DeleteByQueryAsync<Company>(dq =>
                    dq.MaximumDocuments(10).Query(
                            q => q.Match(tr => tr.Field(fd => fd.Description).Query("描述"))).Index(indexName)
                     );
复制代码

 6、更新数据

 除了上述插入数据时自动根据id进行更新外还有以下的主动更新。

 根据id更新单条数据以下代码等价,可以更新部分字段值,但是_id是确定就不会更改的虽然对应的Id字段已被修改:

复制代码
DocumentPath<Company> deletePath = new DocumentPath<Company>("1231");
    var res = await esClient.UpdateAsync(deletePath ,(p) => p.Doc(company).Index(indexName));
    //等价于
    IUpdateRequest<Company, Company> request = new UpdateRequest<Company, Company>(indexName, "1231")
    {
        Doc = new Company()
        {
            Id = "888",
            Description = "11111",
        }
    };
    var res = await esClient.UpdateAsync(request);
复制代码

 如果有多个id更新多条数据可以用如下方法:

var res = esClient.Bulk(b => b.UpdateMany(new List<Company>() { new Company()
    {
        Id="1231",
    } }, (b, u) => b.Id(u.Id).Index(indexName).Doc(new Company { Name = "我无语了" })));

通过条件批量更新如下,

复制代码
var req = new UpdateByQueryRequest<Company>(indexName)
    {
        MaximumDocuments = 10,//一次最多更新几条
        Query = new MatchQuery()
        {
            Field = "description",
            Query = "66",
        },
        Script = new ScriptDescriptor()
        .Source($"ctx._source.description = params.description;")
        .Params(new Dictionary<string, object>
        {
            { "description","小时了123123123"}
        }),
        Refresh = true
    };
    var result = await esClient.UpdateByQueryAsync(req);
复制代码

 7、数据查询

上文中的更新等都用到了查询过滤,此处就用网上的这个例子吧:

复制代码
var result = client.Search<VendorPriceInfo>(
                s => s
                    .Explain() //参数可以提供查询的更多详情。
                    .FielddataFields(fs => fs //对指定字段进行分析
                        .Field(p => p.vendorFullName)
                        .Field(p => p.cbName)
                    )
                    .From(0) //跳过的数据个数
                    .Size(50) //返回数据个数
                    .Query(q =>
                        q.Term(p => p.vendorID, 100) // 主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed的字符串(未经分析的文本数据类型):
                        &&
                        q.Term(p => p.vendorName.Suffix("temp"), "姓名") //用于自定义属性的查询 (定义方法查看MappingDemo)
                        &&
                        q.Bool( //bool 查询
                            b => b
                                .Must(mt => mt //所有分句必须全部匹配,与 AND 相同
                                    .TermRange(p => p.Field(f => f.priceID).GreaterThan("0").LessThan("1"))) //指定范围查找
                                .Should(sd => sd //至少有一个分句匹配,与 OR 相同
                                    .Term(p => p.priceID, 32915),
                                    sd => sd.Terms(t => t.Field(fd => fd.priceID).Terms(new[] {10, 20, 30})),//多值
                                    //||
                                    //sd.Term(p => p.priceID, 1001)
                                    //||
                                    //sd.Term(p => p.priceID, 1005)
                                    sd => sd.TermRange(tr => tr.GreaterThan("10").LessThan("12").Field(f => f.vendorPrice))
                                )
                                .MustNot(mn => mn//所有分句都必须不匹配,与 NOT 相同
                                    .Term(p => p.priceID, 1001)
                                    ,
                                    mn => mn.Bool(
                                        bb=>bb.Must(mt=>mt
                                            .Match(mc=>mc.Field(fd=>fd.carName).Query("至尊"))
                                        ))
                                )
                            )
                    )//查询条件
                .Sort(st => st.Ascending(asc => asc.vendorPrice))//排序
                .Source(sc => sc.Include(ic => ic
                    .Fields(
                        fd => fd.vendorName,
                        fd => fd.vendorID,
                        fd => fd.priceID,
                        fd => fd.vendorPrice))) //返回特定的字段
               );
    
复制代码

 

  分类: .Net Core , elasticsearch

标签:await,indexName,NEST,简单,fd,Elasticsearch,esClient,var,new
From: https://www.cnblogs.com/Leo_wl/p/17404116.html

相关文章

  • containerlab 简单试用
    以下是containerlab简单试用的测试预备需要docker环境安装基于vm运行yum-config-manager--add-repo=https://yum.fury.io/netdevops/&&\echo"gpgcheck=0"|sudotee-a/etc/yum.repos.d/yum.fury.io_netdevops_.reposudoyuminstallcontainerlab......
  • Fuchsia OS 现已支持第二代 Nest Hub
    谷歌神秘新系统Fuchsia正在悄悄普及到更多设备中。作为Android的非 Linux 替代品,Fuchsia已经逐渐在Google的自有智能显示器上进行了推广,首先是第一代NestHub,然后是NestHubMax。意料之中,谷歌现已将Fuchsia悄悄更新到NestHub(2ndGen)中,这也是第三款运行这......
  • Fuchsia OS 现已支持第二代 Nest Hub
    谷歌神秘新系统Fuchsia正在悄悄普及到更多设备中。作为Android的非 Linux 替代品,Fuchsia已经逐渐在Google的自有智能显示器上进行了推广,首先是第一代NestHub,然后是NestHubMax。意料之中,谷歌现已将Fuchsia悄悄更新到NestHub(2ndGen)中,这也是第三款运行这......
  • Fuchsia OS 现已支持第二代 Nest Hub
    谷歌神秘新系统Fuchsia正在悄悄普及到更多设备中。作为Android的非 Linux 替代品,Fuchsia已经逐渐在Google的自有智能显示器上进行了推广,首先是第一代NestHub,然后是NestHubMax。意料之中,谷歌现已将Fuchsia悄悄更新到NestHub(2ndGen)中,这也是第三款运行这......
  • VSCode远程调试Nestjs项目
    在远程服务器中的Nestjs项目中的package.json文件,在scripts中添加或修改"test:debug":"node--inspect-brk={IP:Port}-rtsconfig-paths/register-rts-node/registernode_modules/jest/bin/jest.js--runInBand",在本地相同项目.vscode文件夹下,添加launch.json{"ver......
  • esp8266 水墨屏显示中文之简单字库
    esp8266驱动水墨屏显示中文,假设在此之前已经安装好arduino,配置好esp8266的开发环境。水墨屏显示中文的步骤如下:一、下载库安装esp8266需要的库文件:GxEPD2屏幕驱动库U8g2_for_Adafruit_GFX安装过程可能需要梯子,如果已安装则跳过。二、准备使用打包好的工程驱动屏幕。......
  • 【设计模式】使用 go 语言实现简单工厂模式
    最近在看《大话设计模式》,这本书通过对话形式讲解设计模式的使用场景,有兴趣的可以去看一下。第一篇讲的是简单工厂模式,要求输入两个数和运算符号,得到运行结果。这个需求不难,难就难在类要怎么设计,才能达到可复用、维护性强、可拓展和灵活性高。运算符可能是加、减、乘、除,未了方......
  • Java设计模式-简单工厂模式
    简介在软件开发过程中,设计模式是一种被广泛应用的实践,它是通过总结、归纳和提炼出软件设计经验,从而使得设计更加优雅、高效。简单工厂模式是设计模式中最基本、最简单的一种模式,它能够有效地封装对象的创建过程,简化代码结构。简单工厂模式又称为静态工厂方法模式,它是通过定义一......
  • citect2018R2报警函数练习1-做一个简单的报警显示页面
    这一个笔记我在新浪博客记录过,地址是Citect2018R2报警函数练习1-做一个简单的报警显示页面_来自金沙江的小鱼_新浪博客(sina.com.cn) 这两天看citect一些文档,想着练习一下Cicode的报警函数。新建一个Unity项目,简单的配一下硬件 写简单的程序新建一个Citect2018R2程序,使......
  • 1、nifi-1.9.2介绍、单机部署及简单验证
    文章目录ApacheNiFi系列文章一、Nifi是什么1、dataflow要面临的一些挑战2、Features3、NIFI核心概念4、NiFi单机架构5、NiFi集群架构6、NIFI的性能1)、IO2)、CPU3)、RAM7、NIFI关键特性1)、流管理2)、易用性3)、灵活的缩放模型二、部署1、运行环境2、下载3、单机部署与启动1)、Windows用......