Elasticsearch第五篇:PlainElastic.Net 操作 Elasticsearch
再次强调,我安装的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的更多相关文章
- elasticsearch 第五篇(文档操作接口)
INDEX API 示例: 1 2 3 4 5 PUT /test/user/1 { "name": "silence", "age": 2 ...
- ElasticSearch(五):Java操作ElasticSearch执行查询
package com.gxy.ESChap01; import java.net.InetAddress; import org.elasticsearch.action.search.Search ...
- Elasticsearch入门系列~通过Java一系列操作Elasticsearch
Elasticsearch索引的创建.数据的增删该查操作 上一章节已经在Linux系统上安装Elasticsearch并且可以外网访问,这节主要通过Java代码操作Elasticsearch 1.创建 ...
- R学习笔记 第五篇:字符串操作
文本数据存储在字符向量中,字符向量的每个元素都是字符串,而非单独的字符.在R中,可以使用双引号,或单引号表示字符,函数nchar用于获得字符串中的字符数量: > s='read' > nc ...
- ElasticSearch(七):Java操作elasticsearch基于smartcn中文分词查询
package com.gxy.ESChap01; import java.net.InetAddress; import org.elasticsearch.action.search.Search ...
- ElasticSearch(三):Java操作ElasticSearch索引之CRUD
package com.gxy.ESChap01; import java.net.InetAddress; import java.util.HashMap; import java.util.Ma ...
- R语言学习 第五篇:字符串操作
文本数据存储在字符向量中,字符向量的每个元素都是字符串,而非单独的字符.在R中,可以使用双引号,或单引号表示字符. 一,字符串中的字符数量 函数nchar()用于获得字符串中的字符数量: > s ...
- ElasticSearch(五):简单的ElasticSearch搜索功能
这里主要是一些简单的ElasticSearch的搜索功能,复杂的搜索,比如过滤,聚合等以后单独在写 1. 搜索全部 GET book/_search 直接搜索全部,下面是对搜索结果的详细介绍:默认情况 ...
- 第十五篇:java操作oracle踩坑之旅
最近刚做完mysql的各种需求,项目要满足oracle数据库,于是走上了漫漫的踩坑之路,同行可以看看以免踩坑……第一条:oracle建表的时候不需要在建表sql语句后指定默认字符集 DEFAULT C ...
随机推荐
- Python 为什么用 # 号作注释符?
关于编程语言中的注释,其重要性基本上已为大家所共识. 然而关于注释的规范,这个话题就像我们之前聊过的缩进.终止符和命名方式一样,众口难调. 注释符通常可分为两种,即行注释与块注释(inline/blo ...
- 题解 洛谷 P2086 【[NOI2012]魔幻棋盘】
先考虑只有一维的情况,要求支持区间加和求区间 \(\gcd\),根据 \(\gcd\) 的性质,发现: \[ \gcd(a_1,a_2,a_3,\ldots a_n)=\gcd(a_i,a_2-a_1 ...
- python如何编写win程序
python可以编写win程序.win程序的格式是exe,下面我们就来看一下使用python编写exe程序的方法. 编写好python程序后py2exe模块即可将其打包为exe程序. 实际操作过程: ...
- Java基础之java8新特性(1)Lambda
一.接口的默认方法.static方法.default方法. 1.接口的默认方法 在Java8之前,Java中接口里面的默认方法都是public abstract 修饰的抽象方法,抽象方法并没有方法实体 ...
- Python数据分析之股票数据
最近股市比较火,我7月初上车了,现在已经下了.中间虽然吃了点肉,但下车的时候都亏进去了,最后连点汤都没喝着. 这篇文章我们就用python对股票数据做个简单的分析.数据集是从1999年到2016年上海 ...
- 在同一form表单中如何提交两个不同的action
摘自:CSDN博客 原文链接地址:http://blog.csdn.net/huazhangena/article/details/7903955 有两种办法可以实现:1.针对一个action有多个提 ...
- java实现链表反转
为什么面试常考链表反转 链表是常用的数据结构,同时也是面试常考点,链表为什么常考,因为链表手写时,大多都会有许多坑,比如在添加节点时因为顺序不对的话会让引用指向自己,因此会导致内存泄漏等问题,Java ...
- JavaScript高级程序设计(第三版) 7/25
第七章 函数表达式 1.定义函数的方式有两种,一种是函数声明,一种是函数表达式. //函数声明 function fuc (a){ } //函数表达式 var fuc = function(a){ } ...
- PHP sin() 函数
实例 返回不同数的正弦: <?php高佣联盟 www.cgewang.comecho(sin(3) . "<br>");echo(sin(-3) . " ...
- 2020牛客暑期多校训练营 第二场 J Just Shuffle 置换 群论
LINK:Just Shuffle 比较怂群论 因为没怎么学过 置换也是刚理解. 这道题是 已知一个置换\(A\)求一个置换P 两个置换的关键为\(P^k=A\) 且k是一个大质数. 做法是李指导教我 ...