项目实战 01:将唐诗三百首写入 Elasticsearch 会发生什么?
1、实战项目
将唐诗三百首写入Elasticsearch会发生什么?
2、项目说明
此项目是根据实战项目浓缩的一个小项目,几乎涵盖之前讲解的所有知识点。
通过这个项目的实战,能让你串联起之前的知识点应用于实战,并建立起需求分析、整体设计、数据建模、ingest管道使用、检索/聚合选型、kibana可视化分析等的全局认知。
3、 需求
数据来源:https://github.com/xuchunyang/300
注意数据源bug: 第1753行种的"id":178 需要手动改成 "id": 252。
3.1 数据需求
注意:
-
1)词典选择 -
2)分词器选型 -
3)mapping设置 -
4)支持的目标维度考量 -
5)设定插入时间(自定义动态添加,非人工)
3.2 写入需求
注意:
-
1)特殊字符清洗 -
2)新增插入时间
3.3 分析需求
检索分析DSL实战
-
1)飞花令环节:包含铭 毅 天下(分别包含)诗句有哪些?各有多少首? -
2)李白的诗有几首?按照诗长短排序,由短到长 -
3)取TOP10最长、最短的诗的作者列表
聚合分析实战及可视化实战
-
1)三百首谁的作品最多?取TOP10排行 -
2)五言绝句和七言律诗占比,以及对应作者占比统计 -
3)同名诗排行统计 -
4)三百首诗分词形成什么样的词云
4、 需求解读与设计
4.1 需求解读
本着:编码之前,设计先行的原则。
开发人员的通病——新的项目拿到需求以后,不论其简单还是复杂,都要先梳理需求,整理出其逻辑架构,优先设计,以便建立全局认知,而不是上来就动手敲代码。
本项目的核心知识点涵盖如下几块内容
-
Elasticsearch 数据建模 -
Elasticsearch bulk批量写入 -
Elasticsearch 预处理 -
Elasticsearch检索 -
Elasticsearch聚合 -
kibana Visualize 使用 -
kibana Dashboard 使用
4.2 逻辑架构梳理
有图有真相。
根据需求梳理出如下的逻辑架构,实际开发中要谨记如下的数据流向。
4.3 建模梳理
之前也有讲述,这里再强调一下数据建模的重要性。
数据模型支撑了系统和数据,系统和数据支撑了业务系统。
一个好的数据模型:
-
能让系统更好的集成、能简化接口。 -
能简化数据冗余、减少磁盘空间、提升传输效率。 -
兼容更多的数据,不会因为数据类型的新增而导致实现逻辑更改。 -
能帮助更多的业务机会,提高业务效率。 -
能减少业务风险、降低业务成本。
对于Elasticsearch的数据建模的核心是Mapping的构建。
对于原始json数据:
"id": 251,
"contents": "打起黄莺儿,莫教枝上啼。啼时惊妾梦,不得到辽西。",
"type": "五言绝句",
"author": "金昌绪",
"title": "春怨"
我们的建模逻辑如下:
字段名称 | 字段类型 | 备注说明 |
---|---|---|
_id | 对应自增id | |
contents | text & keyword | 涉及分词,注意开启:fielddata:true |
type | text & keyword | |
author | text & keyword | |
title | text & keyword | |
timestamp | date | 代表插入时间 |
cont_length | long | contents长度, 排序用 |
由于涉及中文分词,选型分词器很重要。
这里依然推荐:选择ik分词。
ik词典的选择建议:自带词典不完备,网上搜索互联网的一些常用语词典、行业词典如(诗词相关词典)作为补充完善。
4.4 概要设计
-
原始文档json的批量读取和写入通过 elasticsearch python低版本 api 和 高版本 api elasticsearch-dsl 结合实现。 -
数据的预处理环节通过 ingest pipeline实现。设计数据预处理地方:每一篇诗的json写入时候,插入timestamp时间戳字段。 -
template和mapping的构建通过kibana实现。 -
分词选型:ik_max_word 细粒度分词,以查看更细粒度的词云。
5、项目实战
5.1 数据预处理ingest
创建:indexed_at 的管道,目的:
-
新增document时候指定插入时间戳字段。 -
新增长度字段,以便于后续排序。
PUT _ingest/pipeline/indexed_at
{
"description": "Adds timestamp to documents",
"processors": [
{
"set": {
"field": "_source.timestamp",
"value": "{{_ingest.timestamp}}"
}
},
{
"script": {
"source": "ctx.cont_length = ctx.contents.length();"
}
}
]
}
5.2 Mapping和template构建
如下DSL,分别构建了模板:my_template。
指定了settings、别名、mapping的基础设置。
模板的好处和便捷性,在之前的章节中有过详细讲解。
PUT _template/my_template
{
"index_patterns": [
"some_index*"
],
"aliases": {
"some_index": {}
},
"settings": {
"index.default_pipeline": "indexed_at",
"number_of_replicas": 1,
"refresh_interval": "30s"
},
"mappings": {
"properties": {
"cont_length":{
"type":"long"
},
"author": {
"type": "text",
"fields": {
"field": {
"type": "keyword"
}
},
"analyzer": "ik_max_word"
},
"contents": {
"type": "text",
"fields": {
"field": {
"type": "keyword"
}
},
"analyzer": "ik_max_word",
"fielddata": true
},
"timestamp": {
"type": "date"
},
"title": {
"type": "text",
"fields": {
"field": {
"type": "keyword"
}
},
"analyzer": "ik_max_word"
},
"type": {
"type": "text",
"fields": {
"field": {
"type": "keyword"
}
},
"analyzer": "ik_max_word"
}
}
}
}
PUT some_index_01
5.3 数据读取与写入
通过如下的python代码实现。注意:
-
bulk批量写入比单条写入性能要高很多。 -
尤其对于大文件的写入优先考虑bulk批量处理实现。
def read_and_write_index():
# define an empty list for the Elasticsearch docs
doc_list = []
# use Python's enumerate() function to iterate over list of doc strings
input_file = open('300.json', encoding="utf8", errors='ignore')
json_array = json.load(input_file)
for item in json_array:
try:
# convert the string to a dict object
# add a new field to the Elasticsearch doc
dict_doc = {}
# add a dict key called "_id" if you'd like to specify an ID for the doc
dict_doc["_id"] = item['id']
dict_doc["contents"] = item['contents']
dict_doc["type"] = item['type']
dict_doc["author"] = item['author']
dict_doc["title"] = item['title']
# append the dict object to the list []
doc_list += [dict_doc]
except json.decoder.JSONDecodeError as err:
# print the errors
print("ERROR for num:", item['id'], "-- JSONDecodeError:", err, "for doc:", dict_doc)
print("Dict docs length:", len(doc_list))
try:
print ("\nAttempting to index the list of docs using helpers.bulk()")
# use the helpers library's Bulk API to index list of Elasticsearch docs
resp = helpers.bulk(
client,
doc_list,
index = "some_index",
doc_type = "_doc"
)
# print the response returned by Elasticsearch
print ("helpers.bulk() RESPONSE:", resp)
print ("helpers.bulk() RESPONSE:", json.dumps(resp, indent=4))
except Exception as err:
# print any errors returned w
## Prerequisiteshile making the helpers.bulk() API call
print("Elasticsearch helpers.bulk() ERROR:", err)
quit()
5.4 数据分析
5.5 检索分析
5.5.1 飞花令环节:包含铭 毅 天下(分别包含)诗句有哪些?各有多少首?
GET some_index/_search
{
"query": {
"match": {
"contents": "铭"
}
}
}
GET some_index/_search
{
"query": {
"match": {
"contents": "毅"
}
}
}
GET some_index/_search
{
"query": {
"match": {
"contents": "天下"
}
}
}
实践表明:
-
铭:0首 -
毅:1首 -
天下:114 首
不禁感叹:唐诗先贤们也是心怀天下,忧国忧民啊!
5.5.2 李白的诗有几首?按照诗长短排序,由短到长
POST some_index/_search
{
"query": {
"match_phrase": {
"author": "李白"
}
},
"sort": [
{
"cont_length": {
"order": "desc"
}
}
]
}
POST some_index/_search
{
"aggs": {
"genres": {
"terms": {
"field": "author.keyword"
}
}
}
}
唐诗三百首中,李白共33首诗(仅次于杜甫39首),最长的是“蜀道难”,共:353 个字符。
李白、杜甫不愧为:诗仙和诗圣啊!也都是高产诗人!
5.5.3 取TOP10最长、最短的诗的作者列表
POST some_index/_search
{
"sort": [
{
"cont_length": {
"order": "desc"
}
}
]
}
POST some_index/_search
{
"sort": [
{
"cont_length": {
"order": "asc"
}
}
]
}
最长的诗:白居易-长恨歌-960个字符。
最短的诗:王维-鹿柴- 24个字符(并列的非常多)。
5.6 聚合分析
以下的截图通过kibana实现。细节在之前的kibana可视化中都有过讲解。
5.6.1 三百首谁的作品最多?取TOP10排行
5.6.2 五言绝句和七言律诗占比,以及对应作者占比统计
5.6.3 同名诗排行统计
5.6.4 三百首诗分词形成什么样的词云
5.6.5 全局视图
6、小结
结合唐诗300首的业务场景,结合本小项目的需求、设计、实现三个阶段,建立起对Elasticsearch、kibana核心知识点的全局认识。
更短时间更快习得更多干货!
中国40%+Elastic认证工程师出自于此!
本文分享自微信公众号 - 铭毅天下(elastic999)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
哦!这该死的 C 语言!
点击蓝色“程序员cxuan”关注我哟 加个“星标”,欢迎来撩 这是程序员cxuan的第 37 期分享 前言 C 语言是一门抽象的、面向过程的语言,C 语言广泛应用于底层开发,C 语言在计算机体系中占据着不可替代的作用,可以说 C 语言是编程的基础,也就是说,不管你学习任何语言,都应该把 C 语言放在首先要学的位置上。下面这张图更好的说明 C 语言的重要性 可以看到,C 语言是一种底层语言,是一种系统层级的语言,操作系统就是使用 C 语言来编写的,比如 Windows、Linux、UNIX 。如果说其他语言是光鲜亮丽的外表,那么 C 语言就是灵魂,永远那么朴实无华。 C 语言特性 那么,既然 C 语言这么重要,它有什么值得我们去学的地方呢?我们不应该只因为它重要而去学,我们更在意的是学完我们能学会什么,能让我们获得什么。 C 语言的设计 C 语言是 1972 年,由贝尔实验室的丹尼斯·里奇(Dennis Ritch)和肯·汤普逊(Ken Thompson)在开发 UNIX 操作系统时设计了C语言。C 语言是一门流行的语言,它把计算机科学理论和工程实践理论完美的融合在一起,使用户能够完成模...
- 下一篇
在 Swift 里安全管理指针
作者:Nemo,iOS 开发者,目前就职于字节跳动 Session:https://developer.apple.com/videos/play/wwdc2020/10167/ 在 Swift 中,我们通过 Unsafe 前缀来标识那些输入后可能发生未定义行为的操作,详情可以回顾WWDC20 - Unsafe Swift[1]。而本文则会更深入地探讨在非安全范围内编写 Swift 的一些细节,日常开发中比较少接触到的部分。 想要更安全地管理指针,意味着需要了解各种导致不安全的方式。指针的安全性可以分为不同级别来讨论,越往底层,程序员越需要为代码的正确性负责。所以日常开发中建议尽量使用顶层的 API 编写代码。 安全级别 安全性可以被分为四个级别。 最顶层的是安全级别,Swift 的主要目标之一就是无需任何不安全的数据结构就能编写代码。Swift 拥有健壮的类型系统,提供了强大的灵活性和性能。完全不使用指针对于代码安全来说是一个很好的选择。 但是 Swift 另一个重要目标是和不安全语言的高性能互操性。所以在第二层 Swift 提供了前缀为 Unsafe 的类型或函数。UnsafePo...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS7设置SWAP分区,小内存服务器的救世主
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7,CentOS8安装Elasticsearch6.8.6
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- 2048小游戏-低调大师作品