1 场景介绍

大数据量的查询问题

假设我们要从商品的表里面查询一个商品

我们的数据库里面肯定有个t_goods的表,我们现在利用商品的名称做模糊查询

1.1 对于数据库的查询的

select * from t_goods where goodsName like “%手机%” ;

问题:

  1. 这个查询速度快不快?
  2. 对于goodsName 是否添加了索引(假设我们添加了)
  3. 对于上面的sql 语句,是否会走索引?

索引的本质是一颗树,若我们使用(“%手机%” ) 查询时,它无法去比较大小,无法比较,就无法走索引!

那种场景走索引:最左匹配原则 goodsName like “手机%”,它会走索引。

goodsName like “%手机” 它不会走索引。

既然不会走索引,它的查询速度,就需要来一个全表的扫描。它的速度会非常慢!

假设我们的数据有百万级别的,查询一个商品,可能就需要20s 左右!

1.2 使用Map 集合来做查询

数据结构如下:Map<String,List<ID>>

我们在Map 集合的Key 放商品的关键字,value放商品的id的集合。

到时我们使用关键字查询商品的ids就可以了

1.3 怎么得到商品的关键字?

商品名称Eg:

【小米10 旗舰新品2月13日14点发布】小米10 骁龙865 5G 抢先预约抽壕礼

荣耀20S 李现同款 3200万人像超级夜景 4800万超广角AI三摄 麒麟810 全网通版

荣耀20i 3200万AI自拍 超广角三摄 全网通版6GB+64GB 渐变红 移动联通电信4G

Redmi 8A 5000mAh 骁龙八核处理器 AI人脸解锁 4GB+64GB 深海蓝 游戏老人手机

1.4 老师问你一个问题:请说出包含 明月的古诗?

明月几时有,把酒问青天(苏东坡《水调歌头》)

海上升明月,天涯共此时(张九龄《望月怀远》)

暗尘随马去,明月逐人来(苏昧道《正月十五夜》)

三五明月满,四五蟾兔缺(无名氏《孟冬寒气至》)

白云还自散,明月落谁家(李白《忆东山二首》)

明月却多情,随人处处行(张先《菩萨蛮》)

明月净松林,千峰同一色(欧阳修《自菩提步月归广化寺》)

明月几时有,把酒问青天(苏轼《水调歌头》)

明月出天山,茫茫人海间(李白《关山月》)

明月照高楼,流光正徘徊(曹植《怨歌行》)

明月隐高树,长河没晓天(陈子昂《春夜别友人》)

举杯邀明月,对影成三人(李白《月下独酌》)

举头望明月,低头思故乡(李白《静夜思》)

深林人不知,明月来相照(王维《竹里馆》)

明月松间照,清泉石上流(王维《山居秋暝》)

如果在使用数据库查询,你只能遍历你学过的每一首诗,看看里面有没有《明月》两个字

如果使用索引:

明月---List<以上所有>

白云---List<忆东山二首>

青天---List<水调歌头>

2 分词实现操作

新建一个maven项目

2.1 导入jieba分词依赖

<dependencies><dependency><groupId>com.huaban</groupId><artifactId>jieba-analysis</artifactId><version>1.0.2</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version></dependency>
</dependencies>

2.2 分词器测试

package com.example.demo;import com.huaban.analysis.jieba.JiebaSegmenter;
import com.huaban.analysis.jieba.SegToken;import java.util.List;public class TestJieBa {//声明一个分词对象private static JiebaSegmenter jiebaSegmenter=new JiebaSegmenter();public static void main(String[] args) {String content="锤子(smartisan) 坚果Pro3 8GB+128GB 黑色 骁龙855PLUS 4800万四摄 全网通双卡双待 全面屏游戏手机";/**** @Description:* 参数1  要分词的内容* 参数1:分词模式*/List<SegToken> tokens = jiebaSegmenter.process(content, JiebaSegmenter.SegMode.SEARCH);for (SegToken token : tokens) {System.out.println(token.word);}System.out.println("分词完成"+tokens.size());}
}

启动后结果如下:

分词器引入成功。

3 使用商品搜索案例来展示我们的Map集合

一下模拟商品查询的过程

3.1 商品实体类

package com.example.demo.domain;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
public class Goods {private Integer id;//商品IDprivate String goodsName;//商品名称private Double goodsPrice;//商品价格
}

3.2 数据库工具类

这边只是模拟数据库,没有进行数据库的连接

package com.example.demo.util;import com.example.demo.domain.Goods;import java.util.*;public class DBUtils {private static Map<Integer, Goods> db=new HashMap<>();public static void insert(Goods goods){db.put(goods.getId(),goods);}public static Goods getById(Integer id){return db.get(id);}/**** @Description:* @Param: 提供一个根据ids的集合查询商品的方法    key--->多个商品ID* @return:*/public static List<Goods> getByIds(Set<Integer> ids){if(null==ids||ids.isEmpty()){return Collections.emptyList();}List<Goods> goods=new ArrayList<>();for (Integer id : ids) {Goods g = db.get(id);if(null!=g){goods.add(g);}}return goods;}
}

3.3 商品服务的接口GoodsService

package com.example.demo.service;import com.example.demo.domain.Goods;import java.util.List;public interface GoodsService {/*** @Description: 添加商品* @Param: [goods]* @return: void*/void insert(Goods goods);/*** @Description: 根据商品名称模糊查询商品* @Param: [goodsName]* @return: java.util.List<com.leige.solr.test.domain.Goods>*/List<Goods> findByGoodsName(String goodsName);
}

3.4 商品服务的实现类(GoodsServiceImpl)

package com.example.demo.service.Impl;import com.example.demo.domain.Goods;
import com.example.demo.service.GoodsService;
import com.example.demo.util.DBUtils;
import com.huaban.analysis.jieba.JiebaSegmenter;
import com.huaban.analysis.jieba.SegToken;import java.util.*;public class GoodsServiceImpl implements GoodsService {//模拟一个索引库private Map<String, Set<Integer>> indexs=new HashMap<>();private JiebaSegmenter jiebaSegmenter=new JiebaSegmenter();@Overridepublic void insert(Goods goods) {/**** 我们在插入商品时,要构造一个Map集合* Map<String,List<ID>/>*///分词List<String> keywords= this.fenci(goods.getGoodsName());//插入数据DBUtils.insert(goods);//保存到分词的关键字和ids的映射关系saveKeyWords(keywords,goods.getId());}/*** @Description: 保存分词和id的关系* @Param: [keywords, id]* @return: void*/private void saveKeyWords(List<String> keywords, Integer id) {if(null!=keywords&&!keywords.isEmpty()){for (String keyword : keywords) {if(indexs.containsKey(keyword)){//先看关键字在索引里面是否存在Set<Integer> integers = indexs.get(keyword);//得到这个关键字对应该的已存在的ids集合integers.add(id);//把新插入的id放入}else{//这是一个新词,之前的索引库不存在HashSet<Integer> ids = new HashSet<>();ids.add(id);indexs.put(keyword,ids);}}}}/**** @Description: 完成分词* @Param: [goodsName]* @return: java.util.List<java.lang.String>*/private List<String> fenci(String goodsName) {List<SegToken> tokens = jiebaSegmenter.process(goodsName, JiebaSegmenter.SegMode.SEARCH);List<String> keywords=new ArrayList<>(tokens.size());for (SegToken token : tokens) {keywords.add(token.word);}return keywords;}/**** @Description: 查询* @Param: [goodsName]* @return: java.util.List<com.leige.solr.test.domain.Goods>*/@Overridepublic List<Goods> findByGoodsName(String goodsName) {//直接从Map里面取有没有if(indexs.containsKey(goodsName)){Set<Integer> ids = indexs.get(goodsName);//取出有goodsName里面有传过来的goodsName商品的IDList<Goods> goodsList = DBUtils.getByIds(ids);return goodsList;}return Collections.emptyList();}
}

3.5 测试类

package com.example.demo;import com.example.demo.domain.Goods;
import com.example.demo.service.GoodsService;
import com.example.demo.service.Impl.GoodsServiceImpl;import java.util.List;public class TestApp {public static void main(String[] args) {GoodsService goodsService = new GoodsServiceImpl();Goods goods = new Goods(1,"苹果手机",10.00) ;Goods goods1 = new Goods(2,"华为手机",11.00) ;Goods goods2 = new Goods(3,"红米手机",5.00) ;Goods goods3 = new Goods(4,"联想手机",6.00) ;goodsService.insert(goods);goodsService.insert(goods1);goodsService.insert(goods2);goodsService.insert(goods3);List<Goods> goodss = goodsService.findByGoodsName("红米");for (Goods goodsTest : goodss) {System.out.println(goodsTest);}}
}

3.6 搜索结果如下

4 缺陷解决

以上代码我们会发现一个问题,我们在搜索红米手机或者其他手机的全名的时候,搜索不出来结果

原因:

分词器对查询的关键字进行分词的时候,对关键字进行了拆分,没有保留原来的完整关键字,

解决方案:

搜索的时候也进行分词

操作如下:

(1)修改GoodsService

/*** @Description: 根据商品名称模糊查询商品* @Param: [goodsName]* @return: java.util.List<com.leige.solr.test.domain.Goods>*/
List<Goods> findByKeyWord(String keyword);

(2)修改GoosServiceImpl

@Override
public List<Goods> findByKeyWord(String keyword) {//先分词  再查询List<String> stringList = this.fenci(keyword);Set<Integer> idsSet = new HashSet<>();for (String kw : stringList) {//直接从Map里面取有没有if(indexs.containsKey(kw)){Set<Integer> ids = indexs.get(kw);//取出有goodsName里面有传过来的goodsName商品的IDidsSet.addAll(ids);}}if(idsSet.isEmpty()){return Collections.emptyList();}else{return DBUtils.getByIds(idsSet);}
}

(3)修改测试类

package com.example.demo;import com.example.demo.domain.Goods;
import com.example.demo.service.GoodsService;
import com.example.demo.service.Impl.GoodsServiceImpl;import java.util.List;public class TestApp {public static void main(String[] args) {GoodsService goodsService = new GoodsServiceImpl();Goods goods = new Goods(1,"苹果手机",10.00) ;Goods goods1 = new Goods(2,"华为手机",11.00) ;Goods goods2 = new Goods(3,"红米手机",5.00) ;Goods goods3 = new Goods(4,"联想手机",6.00) ;goodsService.insert(goods);goodsService.insert(goods1);goodsService.insert(goods2);goodsService.insert(goods3);List<Goods> goodss = goodsService.findByKeyWord("红米手机");for (Goods goodsTest : goodss) {System.out.println(goodsTest);}}
}

结果如下

3.7 对比直接查询

使用分词器之前:是需要把数据库做一个全表的扫描

使用分词器之后:直接通过计算hash值定位 值,在非常理想的情况下。他的速度,只计算一次

jieba分词(1):入门案例相关推荐

  1. 结巴(jieba)分词器入门

    安装jieba # pip install jieba 分词工具 import jieba input="我来到北京大学" seg_list=jieba.cut(input) pr ...

  2. 一文掌握jieba分词器的常见用法,附带案例

    一. jieba分词器的基础知识 安装:pip install jieba 安装:pip3 install paddlepaddle-tiny 如果出现超时的情况,指定清华源:pip3 install ...

  3. Data Mining Machine Learning学习笔记 机器学习入门笔记 之jieba分词(中文分词)(二)

    第二章 Rationlism & Empiricism 理性主义和经验主义 Rationalism (按照人类的方式进行处理,做词法,语法,语义分析) Natural Language Pro ...

  4. 文本分类从入门到精通各种模型的学习——Jieba分词。

    结巴中文分词 Python中文分词组件 四种分词模式 精确模式:试图把句子最精确的切开,适合文本分析. 全模式:把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能解决歧义: 搜索引擎模式: ...

  5. jieba分词_自然语言NLP必备(1),jieba工具 5 行代码对整篇文章分词

    自然语言是什么?下面来看看百度百科的介绍: 自然语言处理是计算机科学领域与人工智能领域中的一个重要方向.它研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法.自然语言处理是一门融语言学.计 ...

  6. 【NLP】jieba分词-Python中文分词领域的佼佼者

    1. jieba的江湖地位 NLP(自然语言)领域现在可谓是群雄纷争,各种开源组件层出不穷,其中一支不可忽视的力量便是jieba分词,号称要做最好的 Python 中文分词组件. "最好的& ...

  7. Spring Data ElasticSearch入门案例

    Spring Data ElasticSearch入门案例 创建maven工程elasticsearch_springdata 基于maven导入坐标 导入spring data elasticsea ...

  8. 自然语言处理系列十七》中文分词》分词工具实战》Python的Jieba分词

    注:此文章内容均节选自充电了么创始人,CEO兼CTO陈敬雷老师的新书<分布式机器学习实战>(人工智能科学与技术丛书)[陈敬雷编著][清华大学出版社] 文章目录 自然语言处理系列十七 分词工 ...

  9. python中正则表达式与jieba分词的使用

    这次和大家分享一下主要使用正则表达式匹配文本信息内容的案例,其中还用到了jieba分词词性标注技术,和一些对文本的切片工作.有兴趣学习的可以详细看看,具体内容,应该有点帮助,这是本人一个一个代码敲出来 ...

最新文章

  1. 记录Android Studio项目提交到github上的出错处理
  2. 八篇 NeurIPS 2019 最新图神经网络相关论文
  3. Keras版Sequence2Sequence对对联实战——自然语言处理技术
  4. 微信小程序支付html标签,微信小程序/支付宝小程序 WxParse解析富文本(html)代码...
  5. Three.js中实现点击按钮添加删除旋转立方体
  6. 廖雪峰历时 3 个月打磨出价值 1980 的数据分析教程,终终终于免费啦!
  7. 存储输出的pickle文件作为数据源
  8. 全国计算机考试光盘,全国计算机一级模拟考试题(光盘).doc
  9. Team Foundation Server 的 Service Pack 1(中文)也发布了,
  10. 使用windows命令和iconv.exe批量转换文件编码
  11. web开发实战--弹出式富文本编辑器的实现思路和踩过的坑
  12. linux复制远程文件和文件夹
  13. 手机android的文件怎么恢复,手机文件误删除怎么恢复-互盾安卓恢复大师
  14. python 报错 IndentationError: unexpected unindent
  15. mac电脑视频去水印
  16. VS2019 C#开发手机App环境配置和开发
  17. 2018_2_3_Boolean Expressions_栈_模拟
  18. PowerDesigner根据数据库生成数据字典
  19. layui 表格数据换行显示
  20. 图像的超分辨率重建SRGAN与ESRGAN

热门文章

  1. 为什么显示D盘可用空间不多,但是明明包括隐藏文件也没有用那么多内存?(内含解决方案)
  2. NC-Verilog仿真
  3. 英菲克I5M_I6M_I7M_I10M-晶晨S805处理器-当贝纯净桌面-线刷固件包
  4. 在线电子书阅读微信小程序 毕业设计(3)图书列表
  5. android 10.0 wifi开关控制
  6. python中英文古风排版_ET(CAD)-中国风复古女唐装制版教程04
  7. 安全狗“老用户推荐新用户”有奖活动进行中 最高IPhone 4S手机
  8. 双十一过后,你的钱包还好嘛?快速回血攻略来了
  9. 手把手阿里云企业邮箱设置教程三步搞定
  10. 去除弹窗遮罩层:modal-append-to-body=“false“