ES倒排序索引

前言

在学习Elasticsearch的使用前,我们先来了解下es是如何实现全文搜索的。

倒排索引是 Elasticsearch 中非常 重要的索引结构,从 文档单词到文档 ID 的过程

为什么要使用倒排索引

先看下面的商品数据goods

id

标题

描述

1

小米手机

小米手机性价比贼高,为发烧而生

2

苹果手机

高端手机,生态丰富

3

三只松鼠零食大礼包

便宜实惠,高端品牌质量有保证

4

小米电脑

小米电脑性价比贼高,便宜好用

如果我们要模糊查含有手机关键词的商品,以mysql查询为例,应该是下面的语句

select * from goods where 标题 like '%手机%' or 描述 like '%手机%'

了解mysql的都知道,用上面的语句查询,索引会失效导致全表查询,如果数据量大的话就会很慢很慢。

怎么解决呢?用倒排索引

倒排索引原理

倒排索引主要包含两个过程:创建倒排索引、倒排索引搜索

创建倒排索引

先对 文档的内容进行分词,形成一个个的 token,也就是 单词,然后保存这些 token 与文档的对应关系。

如上面的商品数据goods,保存后如下所示

token

对应文档

小米

1,4

手机

1,2

苹果

2

电脑

4

三只松鼠

3

零食

3

大礼包

3

便宜

3,4

性价比

1,4

...

...

倒排索引搜索

对搜索词先分词,得到多个Token,然后去倒排索引中进行匹配

如搜索词:性价比手机

分词后:性价比、手机

性价比匹配到的文档是1、4;手机匹配到的文档是1、2

最终搜索到的文档就是1

1

小米手机

小米手机性价比贼高,为发烧而生

实践

简单实现下倒排索引的搜索引擎,中文分词比较麻烦,这里先使用英文,默认英文分词都是空格。

搜索引擎类

class SearchEngines
{
  // 搜索数据
  private $searchData;
  // 搜索
  public function search($keyword)
  {
    // 转小写
    $keyword = strtolower($keyword);
    // 对搜索词进行分词
    $keywords = explode(' ', $keyword);
    $ids = [];
    foreach ($keywords as $keyword) {
      // 查找搜索词对应文档
      $tmpIds = [];
      foreach ($this->searchData[$keyword] as $id) {
        $tmpIds[] = $id;
      }
      // 第一个不取交集
      if (!$ids) {
        $ids = $tmpIds;
        continue;
      }
      // 取搜索词对应文档的交集
      $ids = array_intersect($ids, $tmpIds);
    }
    return $ids;
  }

  // 插入数据
  public function save($id, $keyword)
  {
    // 对关键词进行分词
    $keywords = explode(' ', $keyword);

    foreach ($keywords as $keyword){
      // 都改为小写
      $keyword = strtolower($keyword);
      if (!isset($this->searchData[$keyword])) {
        $this->searchData[$keyword] = [];
      }
      if (!in_array($id, $this->searchData[$keyword])) {
        $this->searchData[$keyword][] = $id;
      }
    }

  }
}

数据插入

$insertData = [
    1 => [
        'id' => 1,
        'title' => 'Xiaomi phones',
        'desc' => 'Xiaomi\'s mobile phone is more cost-effective than thieves, and is born of fever'
    ],
    2 => [
        'id' => 2,
        'title' => 'iPhone',
        'desc' => 'High end mobile phones with rich ecology'
    ],
    3 => [
        'id' => 3,
        'title' => 'Three Squirrels Snack Pack',
        'desc' => 'food'
    ],
    4 => [
        'id' => 4,
        'title' => 'Xiaomi Computer',
        'desc' => 'Xiaomi computers are more cost-effective than thieves, and cheap and easy to use'
    ]
];

$searchEngines = new SearchEngines();
foreach ($insertData as $data) {
    $searchEngines->save($data['id'], $data['title']." ".$data['desc']);
}

关键词搜索

$ids = $searchEngines->search('cost-effective phone');
foreach ($ids as $id) {
  echo $insertData[$id]['title'];
}

执行结果

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值