原创不易,转载请标明地址,或者直接附上我的博客首页https://georgedage.blog.csdn.net/

上篇博客我们说到,数据库为什么不适合搜索引擎的底层存储?,那么什么适合呢?

elasticsearch / solr

那么为什么搜索引擎适合呢?搜索引擎有什么优点呢?下面我们根据提出问题,由浅及深的进行探讨!!!


一、首先分析问题

我们查询时,输入的是苍老师,想要得到标题或内容中包含“苍老师”的新闻列表。怎么办?

有同学会提出,如果标题、内容列上都有一个这样的索引,里面能快速找到与苍老师关键字对应的文章id,再根据文章id就可以快速找到文章了。


二、那么你认为这个索引是什么样的结构呢

在这里,词到文章的索引,我们就称之为倒排索引!!! 也就是搜索引擎的精髓所在。


三、为什么称它为倒排索引?

其实说个秘密,哈哈,也不算秘密,倒排索引英文全名:Inverted Index,然后被国人翻译失败了,翻译成倒排索引,其实它真正的名字应该是反向索引。

那么反向索引还是索引吗?,从这个词上,你或许就能猜到。反向索引本质上其实还是索引,并无特别。

就上面两个图,我们能否将其合并。也就是说


四、上面的两个索引可以合并在一起吗

答案很显然,当然是可以的。

我们自己内心提出问题,为什么要这样做,为什么博主我会说到给两个索引合并在一起。这样做有什么好处?

这个做一个小问题,大家可以思考思考!


五、反向索引的记录数会不会很大

》如果是英文,最大是多少?

》如果是中文,最大是多少?

找了一份资料,资料显示:

所以,我们给出结论:量不会很大,100万以内;通过这个索引找文章会很快。


六、如何建立一个这样的索引

数据示例

新闻id:1

新闻标题:georgedage与乔治一起带球

新闻内容:2025年2月21日,georgedage来到了洛杉矶参加乔治的告别演出,并与乔治进行打球。

》怎样为上面的新闻文章建立反向索引? 一句话怎么分成多个词?人能分,计算机能不能分?


这里我们就引入第二件要说的分词器,也就是我们安装es的时候,提到会安装ik分词器。分词器的原理很简单,这里就是为了告诉大家,你也可以手写分词器!!!

七、分词器原理揭秘——如何建立一个这样的索引

》如果是英文文章,好不好分?

It’sone thing to find the 10 best documents to match your query

英文好分(有空格),中文则不好分。但一定得要分,否则无法建立反向索引。就必须写一套专门]的程序来做这个事情:分词器


八、分词器和自然语言之间的关系

一般来说,每门语言都有其对应的分词器,毕竟整个地球上,大家的语言并不相同。


九、如果要开发一个中文分词器,你觉得该怎么实现对一句话进行分词?

》为什么我们不会分出:张三、说的、的确、确实、实在、在理?

因为我们的大脑可以进行歧义分析。
中文分词器原理:有个词的字典,对语句前后字进行组合,与字典匹配,歧义分析


十、接下来就是我们的重头戏,手写中文分词器

项目结构:

Tokenizer

package com.jd.search;import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;public class Tokenizer {private Map<Character,Object> dictionary;public Tokenizer(String dictionaryFilePath) throws IOException{dictionary = new TreeMap<Character, Object>();//红黑树的实现//从文件加载字典到treeMapthis.loadDictionary(dictionaryFilePath);}private void loadDictionary(String dictionaryFilePath) throws IOException {BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(dictionaryFilePath)));String line = null;while((line = reader.readLine()) != null){line = line.trim();if (line.length() == 0){continue;}char c;Map<Character,Object> child = this.dictionary;//组成以这个字符开头的词的树for (int i = 0; i < line.length(); i++) {c = line.charAt(i);Map<Character,Object> ccMap = (Map<Character, Object>) child.get(c);if (ccMap == null){ccMap = new HashMap<Character, Object>();child.put(c,ccMap);}child = ccMap;}child.put(' ',null);}}public List<String> participle(String text) {if (text == null){return null;}text = text.trim();if (text.length() == 0){return null;}List<String> tokens = new ArrayList<String>();char c;for (int i = 0; i < text.length();) {StringBuilder token = new StringBuilder();Map<Character,Object> child = this.dictionary;boolean matchToken = false;for (int j = i; j < text.length(); j++) {c = text.charAt(j);Map<Character,Object> ccMap = (Map<Character, Object>) child.get(c);if (ccMap == null){if (child.containsKey(' ')){matchToken = true;i = j;}break;}else {token.append(c);child = ccMap;}}if (matchToken){tokens.add(token.toString());}else {if (child.containsKey(' ')){tokens.add(token.toString());break;}else {tokens.add("" + text.charAt(i));i++;}}}return tokens;}public static void main(String[] args) throws IOException {Tokenizer tk = new Tokenizer(Tokenizer.class.getResource("/dictionary.txt").getPath());List<String> tokens = tk.participle("乔治大哥是一个很优秀的博主");for (String s:tokens) {System.out.println(s);}}}

dictionary.txt

乔治大哥
是
一个
很
优秀
的
博主

结果展示:

最后

有什么想聊的,欢迎留言!欢迎吐槽!哈哈

搜索引擎——反向索引原理揭秘及手写ik分词器相关推荐

  1. Vue原理解析:手写路由管理器 —— Vue-Router

    由于时间问题,暂时先把代码完整的贴上来,感兴趣的朋友可以自行研究或收藏.等我那时有时间的时候,对专栏文章进行排序,并逐一讲解代码 一.对外暴露的入口文件index.js import Vue from ...

  2. 深度学习 LSTM长短期记忆网络原理与Pytorch手写数字识别

    深度学习 LSTM长短期记忆网络原理与Pytorch手写数字识别 一.前言 二.网络结构 三.可解释性 四.记忆主线 五.遗忘门 六.输入门 七.输出门 八.手写数字识别实战 8.1 引入依赖库 8. ...

  3. 【干货】JDK动态代理的实现原理以及如何手写一个JDK动态代理

    动态代理 代理模式是设计模式中非常重要的一种类型,而设计模式又是编程中非常重要的知识点,特别是在业务系统的重构中,更是有举足轻重的地位.代理模式从类型上来说,可以分为静态代理和动态代理两种类型. 在解 ...

  4. Elasticsearch——分布式搜索引擎01(索引库、文档、RestAPI、RestClient、拼音分词器、IK分词器)

    Elasticsearch--分布式搜索引擎01(索引库.文档.RestAPI.RestClient.拼音分词器.IK分词器) 一.初识 elesticsearch 1.1 简介 1.2 倒排索引(重 ...

  5. 大数据(7z)Scala手写中文分词

    文章目录 1.手写中文分词极简代码 2.中文分词+Spark词频统计 3.中文分词+Spark文本分类 4.HMM分词(不带词典) 5.HMM分词 1.手写中文分词极简代码 徒手编写Scala中文分词 ...

  6. ElasticSearch入门简介、安装ES(安装Kibana和IK分词器)使用 Postman连接ES进行测、ESRestAPI(操作索引CRUD操作文档CRUD)、练习

    要理解倒排索引 要能够使用DSL命令操作索引库 要能够使用DSL命令操作文档 要能够使用RestAPI操作索引库.文档 一.ES简介 理解倒排索引的概念和作用 理解es和MySql的区别和使用场景 1 ...

  7. solr中的ik分词器的原理是什么

    ik分词器的分词原理本质上是词典分词.现在内存中初始化一个词典,然后在分词过程中挨个读取字符,和字典中的字符相匹配,把文档中的所有词语拆分出来的过程.

  8. ik分词器实现原理_SpringBoot整合Elasticsearch实现商品搜索

    本文主要介绍在Elasticsearch中实现商品搜索功能 中文分词器 Elasticsearch有默认的分词器,默认分词器只是将中文逐词分隔,并不符合我们的需求. get hanzo/_analyz ...

  9. Array.isArray,Array.from, Array.entries,Array.incledes的实现原理,分别手写方法

    1.Array.isArray 基本使用 const arr = ["1"]; console.log("isArray:", Array.isArray(ar ...

最新文章

  1. Spark-Java算子
  2. 用神经网络模拟分子:钠的卤化物
  3. golang基本数据类型转换
  4. Applese 的回文串
  5. 【Boost】boost库中bind的用法
  6. android 网卡监听,Android实时监听网络的变化
  7. HttpServletRequest 需要导入xx包?
  8. 2020年物联网平台调研报告
  9. thrift开源项目研究
  10. Excel去掉下划线首字母小写的公式
  11. 弘辽科技:如何做好淘宝店铺推广?有什么技巧吗?
  12. 手把手教程 | 使用 NICE DCV 在 G4 实例上运行 Android 应用程序
  13. 用计算机演奏歌曲谱子,我要用计算器弹曲子,求亲们发点计算器简谱
  14. Exercise – SE Technical Boot Camp Hands-on Exercises
  15. 从事人工智能行业,推荐的几本书籍
  16. Leetcode 2327. Number of People Aware of a Secret [Python]
  17. MIT一牛人对数学在机器学习中的作用给的评述
  18. Tensorflow新版Seq2Seq接口使用
  19. ubuntu 安装五笔拼音输入法
  20. 使用Dart/Flutter语言开发的命令行文字RPG类型小游戏

热门文章

  1. [C#]我自己写的一个对字节中每位进行修改值的函数
  2. 第五章 MongoDb索引优化 5.6
  3. CodeForces - 1252L Road Construction(基环树+有源汇有上下界的最大流)
  4. POJ - 2018 Best Cow Fences(二分+最长连续子段和)
  5. TensorFlow2-自编码器
  6. Three.js之渲染器
  7. [Windows驱动开发](三)基础知识——驱动例程
  8. 5种IO模式形象的比喻
  9. WebRTC 的版本号与代码分支
  10. C语言程序设计 | 打印一个n行的菱形