再次强调,我安装的Elasticsearch 版本是 7.8.0 ,C# 操作 Elasticsearch 的驱动有 NEST、Elasticsearch.net 、PlainElastic.Net 等,当然要注意版本是否匹配,

PlainElastic.Net 是比较旧的操作 Elasticsearch 的方式 ,但是看到不少园友用这个,所以本篇也用 PlainElastic.Net ,稍后有时间会给出 NEST 、 Elasticsearch.net 的 Demo

PlainElastic.Net 的参考文档、使用方法可以看 https://github.com/Yegoroff/PlainElastic.Net

完整的 Demo 见 https://github.com/fhrddx/ES_Query ,前端 UI 框架是 aceadmin ,见 http://ace.jeka.by/

先看一下效果图

1、首先是封装 ElasticSearchHelper

    public class ElasticSearchHelper
{
public static readonly ElasticSearchHelper Intance = new ElasticSearchHelper(); private ElasticConnection Client; private ElasticSearchHelper()
{
Client = new ElasticConnection("localhost", );
}
}

2、在 ElasticSearchHelper 设定字段mapping 并生成索引库  db_student_test1

    public bool BuildStudentMapping()
{
var mapping = new
{
mappings = new
{
properties = new
{
name = new
{
type = "text",
analyzer = "standard"
},
school = new
{
type = "text",
analyzer = "ik_max_word"
},
desc = new
{
type = "text",
analyzer = "ik_max_word"
},
@class = new
{
type = "integer"
},
chinese = new
{
type = "integer"
},
english = new
{
type = "integer"
},
math = new
{
type = "integer"
}
}
}
};
string jsonDocument = new JsonNetSerializer().Serialize(mapping);
OperationResult operationResult = Client.Put("db_student_test1", jsonDocument);
CommandResult result = new JsonNetSerializer().ToCommandResult(operationResult.Result);
if (result?.acknowledged != null)
return result.acknowledged;
return false;
}

3、在 ElasticSearchHelper中,给与索引库  db_student_test1 一个别名  student_test1

        public bool Alias()
{
OperationResult operationResult = Client.Put("db_student_test1/_alias/student_test1");
CommandResult result = new JsonNetSerializer().ToCommandResult(operationResult.Result);
if (result?.acknowledged != null)
return result.acknowledged;
return false;
}

4、创建索引文档

        public IndexResult CreateIndex(string indexName, string id, string jsonDocument)
{
var serializer = new JsonNetSerializer();
//注意ES版本是8.7.0,type只能是默认的、唯一的 _doc
string cmd = new IndexCommand(indexName, "_doc", id);
Client.Timeout = ;
OperationResult result = Client.Put(cmd, jsonDocument);
var indexResult = serializer.ToIndexResult(result.Result);
return indexResult;
} public IndexResult CreateIndex(string indexName, string id, object document)
{
var serializer = new JsonNetSerializer();
var jsonDocument = serializer.Serialize(document);
return CreateIndex(indexName, id, jsonDocument);
}

5、随机生成测试数据,网上下载一篇txt的长篇小说,随机截取字段,然后写入Elasticsearch

测试数据如下:

    public class TestData
{
public static string xing = @"王李张刘陈杨赵黄周吴徐孙胡朱高林何郭马罗梁宋郑谢韩唐冯于董萧程曹袁邓许傅沈曾彭吕苏卢蒋蔡贾丁魏薛叶阎余潘杜戴夏钟汪田任姜范方石姚谭廖邹熊金陆郝孔白崔康毛邱秦江史顾侯邵孟龙万段雷钱汤尹黎易常武乔贺赖龚文庞樊兰殷施陶洪翟安颜倪严牛温芦季俞章鲁葛伍韦申尤毕聂丛焦向柳邢路岳齐沿梅莫庄辛管祝左涂谷祁时舒耿牟卜肖詹关苗凌费纪靳盛童欧甄项曲成游阳裴席卫查屈鲍位覃霍翁隋植甘景薄单包司柏宁柯阮桂闵欧阳解强柴华车冉房边净阴闫佘练骆付代麦容悲初瞿褚班全名井米谈宫虞奚佟符蒲穆漆卞东储党从艾苻厉岑燕吉冷仇伊首郁娄楚邝历狄简胥连帅封危支原滕苑信索栗官沙池藏师国巩刁茅杭巫居窦皮戈麻饶习巴旷宗荆荣孝蔺廉员西寇刃见底区郦卓琚续朴蒙敖花应喻冀尚顿菅嵇雒弓忻权谌卿扈海冼伦鹿宿山桑裘达么智宣尉迟东方幺郎农戚屠楼步鞠仲尉蓝招攀栾籍寿邬荚税逄加勾由福缑钦鲜于但邸逢况鄢古乐斯钮盖旦毅邰哈鄂商英迟仝亓玄黑腾晏禹诸苟湛殳亢奉占闻粟种匡宾劳申屠伏过水真宇巢计羌相辜展丑银丰矫上昝绳臧舍郅布糜乌衣来恒那满门司徒皋旺公言藤释尧缪干阚靖渠契晋六束良鹗贝邴沃竺扬励归上官荃焉多都果郜隆诸葛令狐慕礼祖翦力朗撖修呼富明站虢冶茹禚笪云肇平弋候尔姬宝畅冒邾延禅浦敬颉南巍补"; public static string name = @"帆栋祜权锟坤允骞谛初盛炳初泽荣喆恒鹤礼华帝宇中鑫彬槐禧允翱鹏皓中伟炳皓槐帆芃欣鑫振杰诚锟潍吉轩福宇初柏芃翰浩峰延帆欣帆奇郁烁卓仕吉帝潍钊杰鑫星谛鑫铭锋沛芃泽禄勇峰欣延鹤郁信侠翰邦寅轩泽哲佑福翱恒文枫澄栋翰中震杞斌凯锦升逸延腾谛权盛弘烁俊强博禄中欣权浩阳裕延盛平畅沛吉强骏起华炳腾柏佑畅杰凯鸿斌加振晨沛祥祜盛濡彬成弘天福锦颖嘉茜芸格美漫慧漫妍钰琪玥沛玥鑫洁岚采曼珍雪昕婷碧弦雪洁馨昕香弦帆芳菲楠俊月珊函蔚帆灵灵莲优蔚碧文蕾娅林婧妮婷薇馨淑惠杉美栀怡薇琪曦云漫瑶韵楠妮颖妮杉媛诗芳菲锦锦蕾芸欢珍岚鹤莉优云舒舒璇慧依菡雅妍楠雅慧灵阳漫珠帆媛可雅欣鑫妮雯霞柔芳芝琳彩冰林媛柔初倩玉冰薇洁妍洁璐采彩颖呈雪云欢琪璟紫静蓓薇欢薇柔晨萱云歆鑫月阳娅媛露露琳"; public static string[] school = new string[] { "中山大学", "暨南大学", "汕头大学", "华南理工大学", "华南农业大学", "广东海洋大学", "广州医科大学", "广州中医药大学", "华南师范大学", "韶关学院", "深圳大学", "广东财经大学", "广东工业大学", "东莞理工学院", "南方科技大学", "香港中文大学", "广州商学院", "上海交通大学", "同济大学", "复旦大学", "上海大学", "上海财经大学", "北京大学", "清华大学", "北京邮电大学", "中国人民大学", "北京理工大学" }; public static string content = @"第一回 甄士隐梦幻识通灵 贾雨村风尘怀闺秀() 此开卷第一回也.作者自云:因曾历过一番梦幻之后,故将真事隐去,而借”通灵”之说,撰此《石头记》一书也.故曰”甄士隐”云云.但书所记何事何人?自又云:“今风尘碌碌,一事无成,忽念及当日所有之女子,一一细考较去,觉其行止见识,皆出于我之上.何我堂堂须眉,诚不若彼裙钗哉?实愧则有余,悔又无益之大无可如何之日也!当此,则自欲将已往所赖天恩祖德,锦衣纨绔之时,饫甘餍肥之日,背父兄教育之恩,负师友规谈之德,以至今日一技无成,半生潦倒之罪,编述一集,以告天下人:我之罪固不免,然闺阁本自历历有人,万不可因我之不肖,自护己短,一并使其泯灭也.虽今日之茅椽蓬牖,瓦灶绳床,其晨夕风露,阶柳庭花,亦未有妨我之襟怀笔墨者.虽我未学,下笔无,又何妨用假语村言,敷演出一段故事来,亦可使闺阁昭传,复可悦世之目,破人愁闷,不亦宜乎?”故曰”贾雨村”云云.
......
......
由来同一梦,休笑世人痴!";
}

随机生成学生记录的代码如下:

            int xing_length = TestData.xing.Length;
int name_length = TestData.name.Length;
int school_length = TestData.school.Length;
int content_length = TestData.content.Length; ParallelOptions _po = new ParallelOptions();
_po.MaxDegreeOfParallelism = ;
Parallel.For(, , _po, c =>
{
Random r = new Random(c);
Random r2 = new Random();
try
{
string desc = TestData.content.Substring((r.Next(, content_length - )), ).Trim().Replace("/r/n", string.Empty);
Student model = new Student()
{
name = TestData.xing[r.Next(, xing_length)].ToString() + TestData.name.Substring(r.Next(, name_length / ) * , ),
school = TestData.school[r.Next(, school_length)],
chinese = r.Next(, ) + r2.Next(, ),
math = r.Next(, ) + r2.Next(, ),
english = r.Next(, ) + r2.Next(, ),
@class = c,
desc = desc + TestData.school[r2.Next(, school_length)]
};
ElasticSearchHelper.Intance.CreateIndex("db_student_test1", Guid.NewGuid().ToString(), model);
}
catch (Exception ex)
{
Console.Write(ex.ToString());
}
});

6、单个词语查询,例如查询满足以下条件的文档:(1) desc 包含 “黛玉” (2)chinese、math、english 都大于90(3)分页取前10条记录(4)关键词高亮(5)排序按照语文、数学、英语倒序

controller 代码如下

        public ActionResult Index(string key = "黛玉")
{
Stopwatch sw = new Stopwatch();
sw.Restart();
var model = ElasticSearchHelper.Intance.Term(key.Trim(), , );
sw.Stop();
ViewBag.Message = $"共耗时{sw.ElapsedMilliseconds}毫秒";
return View(model);
}

ElasticsearchHelper 代码如下

        public ElasticsearchResult<Student> Term(string key, int from = , int size = )
{
if (string.IsNullOrEmpty(key))
return null; key = key.Trim();
string cmd = new SearchCommand("student_test1", "_doc");
var query = new QueryBuilder<Student>().Query(
b => b.Bool(m => m.Must(t =>
t.Term(d => d.Field("desc").Value(key))
.Range(d => d.Field("chinese").From("").To(""))
.Range(d => d.Field("math").Gt(""))
.Range(d => d.Field("english").Gt(""))
)
)
)
.From(from)
.Size(size)
.Sort(s => s.Field("chinese", SortDirection.desc).Field("math", SortDirection.desc).Field("english", SortDirection.desc))
.Highlight(h => h
.PreTags("<span class=\"label label-sm label-danger\">")
.PostTags("</span>")
.Fields(
f => f.FieldName("desc").Order(HighlightOrder.score)
)
)
.Build(); string result = Client.Post(cmd, query);
var list = new JsonNetSerializer().Deserialize<ElasticsearchResult<Student>>(result);
return list;
}

效果是

7、语句匹配查询,关键词是“黛玉”,当然是可以查出来,但是如果用户知道红楼梦有个情节,是关于大观园里众人举办螃蟹宴,作诗玩乐的,想把相关文段查询出来,这时用户输入的关键词是 “宝玉黛玉螃蟹宴作诗” ,这时候会查询出什么呢?

首先改一下逻辑,controller 代码为

       public ActionResult Query(string key = "宝玉黛玉螃蟹宴作诗")
{
Stopwatch sw = new Stopwatch();
sw.Restart();
var model = ElasticSearchHelper.Intance.Query(key.Trim(), , );
sw.Stop();
ViewBag.Message = $"共耗时{sw.ElapsedMilliseconds}毫秒";
return View("~/Views/ES/Index.cshtml", model);
}

ElasticsearchHelper 代码如下

        public ElasticsearchResult<Student> Query(string key, int from = , int size = )
{
if (string.IsNullOrEmpty(key))
return null; key = key.Trim();
string cmd = new SearchCommand("student_test1", "_doc");
var query = new QueryBuilder<Student>().Query(
b => b.Bool(m => m.Must(t =>
//其实也是可以用 t.match() 的,可以试一下
t.QueryString(d => d.DefaultField("desc").Query(key))
.Range(d => d.Field("chinese").From("").To(""))
.Range(d => d.Field("math").Gt(""))
.Range(d => d.Field("english").Gt(""))
)
)
)
.From(from)
.Size(size)
//这里不再按照分数来排序,这时ES会根据关键词匹配度来排序,出现在最前的,应该是最匹配的
//.Sort(s => s.Field("chinese", SortDirection.desc).Field("math", SortDirection.desc).Field("english", SortDirection.desc))
.Highlight(h => h
.PreTags("<span class=\"label label-sm label-danger\">")
.PostTags("</span>")
.Fields(
f => f.FieldName("desc").Order(HighlightOrder.score)
)
)
.Build(); string result = Client.Post(cmd, query);
var list = new JsonNetSerializer().Deserialize<ElasticsearchResult<Student>>(result);
return list;
}

查询结果是

可以看到,ES 会把  “宝玉黛玉螃蟹宴作诗” 进行分词,然后进行文本匹配。

PlainElastic.Net 是比较旧的版本了,不是很适合ES版本 7.8.0 可以用 NEST 或者 Elasticsearch.net ,我这里是参考一些园友,然后写个Demo出来测试一下。

(未完,ES 聚合统计的,待续)

Elasticsearch第五篇:PlainElastic.Net 操作 Elasticsearch的更多相关文章

  1. elasticsearch 第五篇(文档操作接口)

    INDEX API 示例: 1 2 3 4 5 PUT /test/user/1 { "name": "silence", "age": 2 ...

  2. ElasticSearch(五):Java操作ElasticSearch执行查询

    package com.gxy.ESChap01; import java.net.InetAddress; import org.elasticsearch.action.search.Search ...

  3. Elasticsearch入门系列~通过Java一系列操作Elasticsearch

    Elasticsearch索引的创建.数据的增删该查操作 上一章节已经在Linux系统上安装Elasticsearch并且可以外网访问,这节主要通过Java代码操作Elasticsearch 1.创建 ...

  4. R学习笔记 第五篇:字符串操作

    文本数据存储在字符向量中,字符向量的每个元素都是字符串,而非单独的字符.在R中,可以使用双引号,或单引号表示字符,函数nchar用于获得字符串中的字符数量: > s='read' > nc ...

  5. ElasticSearch(七):Java操作elasticsearch基于smartcn中文分词查询

    package com.gxy.ESChap01; import java.net.InetAddress; import org.elasticsearch.action.search.Search ...

  6. ElasticSearch(三):Java操作ElasticSearch索引之CRUD

    package com.gxy.ESChap01; import java.net.InetAddress; import java.util.HashMap; import java.util.Ma ...

  7. R语言学习 第五篇:字符串操作

    文本数据存储在字符向量中,字符向量的每个元素都是字符串,而非单独的字符.在R中,可以使用双引号,或单引号表示字符. 一,字符串中的字符数量 函数nchar()用于获得字符串中的字符数量: > s ...

  8. ElasticSearch(五):简单的ElasticSearch搜索功能

    这里主要是一些简单的ElasticSearch的搜索功能,复杂的搜索,比如过滤,聚合等以后单独在写 1. 搜索全部 GET book/_search 直接搜索全部,下面是对搜索结果的详细介绍:默认情况 ...

  9. 第十五篇:java操作oracle踩坑之旅

    最近刚做完mysql的各种需求,项目要满足oracle数据库,于是走上了漫漫的踩坑之路,同行可以看看以免踩坑……第一条:oracle建表的时候不需要在建表sql语句后指定默认字符集 DEFAULT C ...

随机推荐

  1. 【JVM之内存与垃圾回收篇】程序计数器

    程序计数器 介绍 JVM 中的程序计数寄存器(Program Counter Register)中,Register 的命名源于 CPU 的寄存器,寄存器存储指令相关的现场信息.CPU 只有把数据装载 ...

  2. Elasticsearch源码解析:环境搭建

    在之前学习Redis的过程中,我就是一边通过文档/视频学习,一边阅读源码.我发现两种方法可以相辅相成,互相补充.阅读文档可以帮助我们快速了解某个功能,阅读源码有助于我们更深入的理解这一功能的实现及思想 ...

  3. 完全卸载MySQL完整图文流程

    想把mlsql卸载了重装,看了许多文章试了很多方法都没办法完全卸载,直到看到了这篇文章, 可以完全卸载mysql,在这里谢谢博主,也拿出来分享给大家 原文链接:https://blog.csdn.ne ...

  4. 网页批量打印成PDF,并按条件合并成大PDF、生成页码

    题记:因为老板要求将过去一年内系统中的订单合同内容进行打印,并按月进行整理成纸质文件.合同在系统(web系统)中以html形式显示,打印单份都是在网页中右键打印,订单量上千份,每笔订单有两份合同,如果 ...

  5. form表单两种提交方式的不同

      我们在使用<Form>表单的时候,最常用的提交方式就是Get和Post.我们都知道这两种方式最大的差别就是安全性,除此之外,它们还有哪些其他的区别,你知道吗?   在<Form& ...

  6. RecyclerView设置空视图

    RecyclerView貌似不能直接设置空视图,所以可以自定义一个RecyclerView继承自RecyclerView并设置一个数据监听者监视数据状态. MyCyclerView.java pack ...

  7. kylin streaming原理介绍与特点浅析

    目录 前言 kylin streaming设计和原理 架构介绍 streaming coordinator streaming receiver cluster kylin streaming数据构建 ...

  8. IDEA 修改快捷键和Myeclipse 快捷键一致

    介绍 我们知道IDEA这款开发工具功能很强大,为了简化开发步骤,提高开发效率,使用快捷键很显然是必不可少的,那么怎么才能使得IDEA快捷键和MyEclipse快捷键 保持相同呢? 第一种方法,一个快捷 ...

  9. 你不知道的JavaScript 上卷 2/11

    第一部分——作用域和闭包 第一章 作用域是什么 1.几乎所有编程语言最基本的功能之一,就是能够储存变量当中的值,并且能在之后对这个值进行访问或修改.事实上,正是这种储存和访问变量的值的能力将状态带给了 ...

  10. 读取 csv , xlsx 表格并添加总分列

    import pandas as pd import numpy as np data = pd.read_excel('学生成绩表.csv',columns = ['学号','姓名','高数','英 ...