网站首页 > 技术文章 正文
项目概述
我们的需求是要开发一个阅读平台系统,为了方便用户快速的搜索书籍,我们当然要开发一个搜索功能,目标是根据书籍的 书名,作者,分类,书籍标签精准搜索书籍列表。期望达到以下效果:
模糊搜索:用户输入关键词后,显示的搜索结果是一些包含该关键词的信息和数据又或者说跟关键词相关的信息。
结果分类:在同一个搜索的反馈结果过程中,往往包含多个不同类型搜索结果,从用户输入的关键字来看,往往存在很强的主观性,但是系统很难判断出用户到底想搜索的类型是什么;因此,在做搜索结果页面设计的时候要考虑是否将搜索结果进行分类,不同类型的类别应该有哪些?如:根据书籍名称搜索,书籍标签搜索,作者搜索。
筛选排序:在搜索结果反馈的页面中,遇到搜索结果的内容体量和内容属性比较丰富时,这时对于用户来说难以快速找到自己想要搜索的内容;为了缩小内容列表规模和提升用户搜索效率,通常会在搜索结果页面设置筛选和排序功能。
高亮显示:很多时候,在搜索结果反馈列表中,会对内容中的用户输入的关键词做特殊处理,大多数是改变字体或者字体颜色,将输入的关键词与其他内容区分开来;这样做的目的主要是减少用户的选择成本,让用户能够快速获得自己所期望的搜索结果。
效果图:
技术选型
书籍搜索功能是一个典型的读多写少的场景。书籍由我们签约的第三方平台提供,我们根据规则配置动态的从多个第三方平台拉取书籍信息数据。用户通过APP等其他渠道可以搜索喜欢的书籍。
通用的垂直化搜索引擎开源组件包括:Elastic Search 和 Solr。我们选择使用Elastic Search开发我们的书籍搜索功能。
读多写少的场景非常适合使用查询责任分离(CQRS)开发。
书籍搜索: CQRS?
命令查询责任分离(CQRS)是一种强大的架构模式,它将软件系统中处理命令和查询的责任分开。通过划分这些关注点,CQRS 可提高可扩展性、可维护性和灵活性。CQRS 是 "命令查询责任隔离"(Command Query Responsibility Segregation)的缩写。这是一种将读取数据(查询)和写入数据(命令)的操作分开的模式。在基于 CQRS 的系统中,通常涉及以下组件:
Command:代表改变系统数据的操作。命令负责创建、更新或删除数据。
Query:表示从系统检索数据的操作。查询负责读取数据而不修改数据。
Command Handler:处理和执行命令,更改系统状态。
Query Handler:通过从系统检索数据并以合适的格式返回数据来处理查询。
书籍抓取
详细设计,请参考:Redis进阶六之分布式任务
抓取类设计:
Elastic Search集群架构视图
第一步:准备索引 mapping
使用以下命令查看mapping [只展示了部分属性],使用 kibana 演示效果。
GET /index/_mappings
{
"book_index" : {
"mappings" : {
"dynamic" : "false",
"dynamic_templates" : [
{
"message_full" : {
"match" : "message_full",
"mapping" : {
"fields" : {
"keyword" : {
"ignore_above" : 2048,
"type" : "keyword"
}
},
"type" : "text"
}
}
},
{
"message" : {
"match" : "message",
"mapping" : {
"type" : "text"
}
}
},
{
"strings" : {
"match_mapping_type" : "string",
"mapping" : {
"type" : "keyword"
}
}
}
],
"properties" : {
"author" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword"
}
},
"analyzer" : "ik_max_word",
"search_analyzer" : "ik_smart"
},
"bookDesc" : {
"type" : "text",
"analyzer" : "ik_max_word",
"search_analyzer" : "ik_smart"
},
"bookName" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword"
}
},
"analyzer" : "ik_max_word",
"search_analyzer" : "ik_smart"
},
"bookTags" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword"
}
},
"analyzer" : "ik_max_word",
"search_analyzer" : "ik_smart"
},
"categoryId" : {
"type" : "integer"
},
"categoryName" : {
"type" : "text",
"analyzer" : "ik_max_word",
"search_analyzer" : "ik_smart"
},
"channelType" : {
"type" : "integer"
},
"chaptersCount" : {
"type" : "integer"
},
"cover" : {
"type" : "keyword"
},
"createTime" : {
"type" : "date",
"format" : "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
},
"id" : {
"type" : "integer"
},
"readCount" : {
"type" : "long"
},
"score" : {
"type" : "double"
},
"wordNumber" : {
"type" : "long"
}
}
}
}
}
第二步:根据关键字搜索
根据 书籍名称,作者,书籍标签搜索
POST /book_index/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"bookName": "大唐"
}
},
{
"match": {
"author": "大唐"
}
},
{
"match": {
"bookTags.keyword": "大唐"
}
}
]
}
},
"_source":["bookName","author","bookTags"],
"from": 10,
"size": 10
}
搜索结果:
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 98,
"relation" : "eq"
},
"max_score" : 17.087156,
"hits" : [
{
"_index" : "book_index",
"_type" : "_doc",
"_id" : "12510",
"_score" : 14.329958,
"_source" : {
"author" : "骑鹤下扬州",
"bookName" : "大唐:贞观第一败家子",
"bookTags" : [
"穿越",
"历史",
"架空",
"大唐",
"系统",
"爽文"
]
}
},
{
"_index" : "book_index",
"_type" : "_doc",
"_id" : "12791",
"_score" : 14.1536045,
"_source" : {
"author" : "唐公子",
"bookName" : "大唐:开局暴打唐太宗",
"bookTags" : [
"历史",
"架空",
"大唐",
"穿越"
]
}
},
{
"_index" : "book_index",
"_type" : "_doc",
"_id" : "1968",
"_score" : 13.994913,
"_source" : {
"author" : "笑君",
"bookName" : "神级卡牌系统大唐最强店长",
"bookTags" : [
"穿越",
"大唐",
"爽文",
"系统"
]
}
},
{
"_index" : "book_index",
"_type" : "_doc",
"_id" : "12767",
"_score" : 13.994913,
"_source" : {
"author" : "唐公子",
"bookName" : "大唐:我被女帝偷听了心声",
"bookTags" : [
"穿越",
"系统",
"女帝",
"大唐"
]
}
},
{
"_index" : "book_index",
"_type" : "_doc",
"_id" : "19532",
"_score" : 13.740128,
"_source" : {
"author" : "朱凤九",
"bookName" : "这个大唐我来救",
"bookTags" : [
"架空",
"爽文",
"权谋",
"大唐"
]
}
},
{
"_index" : "book_index",
"_type" : "_doc",
"_id" : "342",
"_score" : 9.99041,
"_source" : {
"author" : "红娘子",
"bookName" : "西游密码之黄金丝路",
"bookTags" : [
"穿越",
"大唐",
"爽文",
"热血"
]
}
},
{
"_index" : "book_index",
"_type" : "_doc",
"_id" : "1876",
"_score" : 9.99041,
"_source" : {
"author" : "饭团子",
"bookName" : "西游:我成了三界焦点",
"bookTags" : [
"西游",
"穿越",
"大唐",
"脑洞"
]
}
},
{
"_index" : "book_index",
"_type" : "_doc",
"_id" : "18910",
"_score" : 9.236053,
"_source" : {
"author" : "罗诜",
"bookName" : "回到唐朝当驸马",
"bookTags" : [
"架空",
"大唐",
"历史",
"系统",
"爽文"
]
}
},
{
"_index" : "book_index",
"_type" : "_doc",
"_id" : "18621",
"_score" : 8.705441,
"_source" : {
"author" : "我爱大包子",
"bookName" : "回到唐朝当太子",
"bookTags" : [
"穿越",
"热血",
"架空",
"爽文",
"权谋",
"大唐"
]
}
},
{
"_index" : "book_index",
"_type" : "_doc",
"_id" : "18941",
"_score" : 8.705441,
"_source" : {
"author" : "烈玄",
"bookName" : "逆宋",
"bookTags" : [
"穿越",
"热血",
"架空",
"爽文",
"权谋",
"大唐"
]
}
}
]
}
}
猜你喜欢
- 2024-10-29 你还在用 Date?快使用 LocalDateTime 了!
- 2024-10-29 Java修炼终极指南:79,80,81 签到终极修炼天赋
- 2024-10-29 硬核!最全的延迟任务实现方式汇总!附代码(强烈推荐)
- 2024-10-29 还在实体类中用Date?JDK8新的日期类型不香么?
- 2024-10-29 LocalDateTime 说:2020,是时候换个更好的日期时间类了
- 2024-10-29 程序员,你还在使用Date嘛?建议你使用LocalDateTime哦
- 2024-10-29 深度思考:在JDK8中,日期类型该如何使用?
- 2024-10-29 为什么建议使用你 LocalDateTime,而不是 Date?
- 2024-10-29 百度开源的分布式唯一ID生成器UidGenerator,解决了时钟回拨问题
- 2024-10-29 DeepLearning4j 实战:手写体数字识别的 GPU 实现与性能对比
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- oraclesql优化 (66)
- 类的加载机制 (75)
- feignclient (62)
- 一致性hash算法 (71)
- dockfile (66)
- 锁机制 (57)
- javaresponse (60)
- 查看hive版本 (59)
- phpworkerman (57)
- spark算子 (58)
- vue双向绑定的原理 (68)
- springbootget请求 (58)
- docker网络三种模式 (67)
- spring控制反转 (71)
- data:image/jpeg (69)
- base64 (69)
- java分页 (64)
- kibanadocker (60)
- qabstracttablemodel (62)
- java生成pdf文件 (69)
- deletelater (62)
- com.aspose.words (58)
- android.mk (62)
- qopengl (73)
- epoch_millis (61)
本文暂时没有评论,来添加一个吧(●'◡'●)