您的位置 首页 java

最受欢迎的企业搜索引擎Elasticsearch在Python中的应用

简介

You know, for search!

Elasticsearch 是一个开源的搜索引擎,建立在一个全文搜索引擎库 Apache Lucene™ 基础之上。Elasticsearch 也是使用 Java 编写的,它的内部使用 Lucene 做索引与搜索,但是它的目的是使全文检索变得简单, 通过隐藏 Lucene 的复杂性,取而代之的提供一套简单一致的 RESTful API。然而,Elasticsearch 不仅仅是 Lucene,并且也不仅仅只是一个全文搜索引擎。 它可以被下面这样准确的形容:

  • 一个 分布式 的实时文档存储,每个字段 可以被索引与搜索
  • 一个分布式实时分析搜索引擎
  • 能胜任上百个服务节点的扩展,并支持 PB 级别的结构化或者非结构化数据

它提供了一个分布式、支持多用户的全文搜索引擎, 具有HTTP Web接口和无模式JSON文档。 所有其他语言可以使用 RESTful API 通过端口 9200 和 Elasticsearch 进行通信

Elasticsearch是用Java开发的 ,并在Apache许可证下作为开源软件发布。官方客户端在Java、.NET(C#)、PHP、Python、Apache Groovy、 Ruby 和许多其他语言中都是可用的。

根据DB-Engines的排名显示, Elasticsearch是最受欢迎的企业搜索引擎 ,其次是Apache Solr,也是基于Lucene。

Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。

Elasticsearch是分布式的 ,这意味着索引可以被分成分片,每个分片可以有0个或多个副本。每个节点托管一个或多个分片,并充当协调器将操作委托给正确的分片。再平衡和路由是自动完成的。相关数据通常存储在同一个索引中,该索引由一个或多个主分片和零个或多个复制分片组成。一旦创建了索引,就不能更改主分片的数量。

Elasticsearch 是一个实时的分布式搜索分析引擎,它被用作全文检索、结构化搜索、分析以及这三个功能的组合。

Elasticsearch 将所有的功能打包成一个单独的服务,这样你可以通过程序与它提供的简单的 RESTful API 进行通信, 可以使用自己喜欢的编程语言充当 web 客户端,甚至可以使用命令行(去充当这个客户端)。

就 Elasticsearch 而言,起步很简单。对于初学者来说,它预设了一些适当的默认值,并隐藏了复杂的搜索理论知识。 它 开箱即用 。只需最少的理解,你很快就能具有生产力。

Elasticsearch 是 面向文档 的,意味着它存储整个对象或 文档。Elasticsearch 不仅存储文档,而且 索引每个文档的内容使之可以被检索。在 Elasticsearch 中,你 对文档进行索引、检索、排序和过滤–而不是对行列数据。

Elasticsearch 有2.x、5.x、6.x 三个大版本。 更多了解可以访问 elastic中文社区

原理: 倒排索引 、分析、相关性排序

它基于Lucene,Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。在传统全文检索引擎的倒排索引的基础上,实现了分块索引。接下来介绍一下 倒排索引。

倒排索引(英语:Inverted index) ,也常被称为反向索引、置入档案或反向档案,是一种索引方法,被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射。它是文档检索系统中最常用的数据结构。通过倒排索引,可以根据单词快速获取包含这个单词的文档列表。倒排索引主要由两个部分组成:“单词词典”和“倒排文件”。

以下图为例子:

假设我们有两个文档,每个文档的 content 域包含如下内容:

  1. The Quick brown fox jumped over the , lazy+ dog
  2. Quick brown foxes leap over lazy dogs in summer

反向索引:

如果我们想搜索 quick brown ,我们只需要查找包含每个词条的文档:

两个文档都匹配,但是第一个文档比第二个匹配度更高。如果我们使用仅计算匹配词条数量的简单 相似性算法 ,那么,我们可以说,对于我们查询的相关性来讲,第一个文档比第二个文档更佳。分析

分析

上面不太合理的地方:

  • Quick 和 quick 以独立的词条(token)出现,然而用户可能认为它们是相同的词。
  • fox 和 foxes 非常相似, 就像 dog 和 dogs ;他们有相同的词根。
  • jumped 和 leap, 尽管没有相同的词根,但他们的意思很相近。他们是同义词。

进行 标准化

  • Quick 可以小写化为 quick 。
  • foxes 可以 词干提取 –变为词根的格式– 为 fox 。类似的, dogs 可以为提取为 dog 。
  • jumped 和 leap 是同义词,可以索引为相同的单词 jump 。

标准化的反向索引:

对于查询的 字符串 必须与词条(token)进行相同的标准化处理,才能保证搜索的正确性。

分词和标准化的过程称为 分析 (analysis) :

  • 首先,将一块文本分成适合于倒排索引的独立的 词条 , -> 分词
  • 之后,将这些词条统一化为标准格式以提高它们的“可搜索性” -> 标准化

分析工作是由 分析器 完成的: analyzer

  • 字符 过滤器 首先,字符串按顺序通过每个 字符过滤器 。他们的任务是在分词前整理字符串。一个字符过滤器可以用来去掉HTML,或者将 & 转化成 and。
  • 分词器其次,字符串被 分词器 分为单个的词条。一个简单的分词器遇到空格和标点的时候,可能会将文本拆分成词条。
  • Token 过滤器 (词条过滤器)最后,词条按顺序通过每个 token 过滤器 。这个过程可能会改变词条(例如,小写化 Quick ),删除词条(例如, 像 a, and, the 等无用词),或者增加词条(例如,像 jump 和 leap 这种同义词)。

相关性排序

默认情况下,搜索结果是按照 相关性 进行倒序排序的——最相关的文档排在最前。

相关性可以用相关性评分表示,评分越高,相关性越高。

评分的计算方式取决于查询类型 不同的查询语句用于不同的目的: fuzzy 查询(模糊查询)会计算与关键词的拼写相似程度,terms 查询(词组查询)会计算 找到的内容与关键词组成部分匹配的百分比,但是通常我们说的 相关性 是我们用来计算全文本字段的值相对于全文本 检索词 相似程度的算法。

Elasticsearch 的相似度算法 被定义为检索词频率/反向文档频率, TF/IDF ,包括以下内容:

  • 检索词频率检索词在该字段出现的频率?出现频率越高,相关性也越高。 字段中出现过 5 次要比只出现过 1 次的相关性高。
  • 反向文档频率每个检索词在索引中出现的频率?频率越高,相关性越低。检索词出现在多数文档中会比出现在少数文档中的权重更低。
  • 字段长度准则字段的长度是多少?长度越长,相关性越低。 检索词出现在一个短的 title 要比同样的词出现在一个长的 content 字段权重更大。

elasticsearch python客户端使用

  • 安装
 pip install elasticsearch  
  • 对于elasticsearch 5.x 版本 需要按以下方式导入
 from elasticsearch5 import Elasticsearch

# elasticsearch集群服务器的地址
ES = [
    '127.0.0.1:9200'
]

# 创建elasticsearch客户端
es = Elasticsearch(
    ES,
    # 启动前嗅探es集群服务器
    sniff_on_start=True,
    # es集群服务器结点连接异常时是否刷新es结点信息
    sniff_on_connection_fail=True,
    # 每60秒刷新结点信息
    sniffer_timeout=60
)  
  • 搜索使用方式
 query = {
    'query': {
        'bool': {
            'must': [
                {'match': {'_all': 'python web'}}
            ],
            'filter': [
                {'term': {'status': 2}}
            ]
        }
    }
}
ret = es.search(index='articles', doc_type='article', body=query)  

当然如果你想要在自己的Linux系统或者Windows中安装Elasticsearch,可以参考百度中的各种答案,按照步骤一步一步来,本文就不具体介绍了。

分词器 我们以 IK中文分析器 为例:

安装包可以去官网下载,或者私信我回复: IK 获取。

  • 安装
 sudo /usr/share/elasticsearch/bin/elasticsearch-plugin install file:///home/python/elasticsearch-analysis-ik-5.6.16.zip  
  • 重新启动
 sudo systemctl restart elasticsearch  
  • 测试分析器
 curl -X GET 127.0.0.1:9200/_analyze?pretty -d '
{
  "analyzer": "standard",
  "text": "我是&中国人"
}'

curl -X GET 127.0.0.1:9200/_analyze?pretty -d '
{
  "analyzer": "ik_max_word",
  "text": "我是&中国人"
}'  

Elasticsearch 集群(cluster)

Elasticsearch 尽可能地屏蔽了分布式系统的复杂性。这里列举了一些在后台自动执行的操作:

  • 分配文档到不同的容器 或 分片 中,文档可以储存在一个或多个节点中
  • 按集群节点来均衡分配这些分片,从而对索引和搜索过程进行负载均衡
  • 复制每个分片以支持数据冗余,从而防止硬件故障导致的数据丢失
  • 将集群中任一节点的请求路由到存有相关数据的节点
  • 集群扩容时无缝整合新节点,重新分配分片以便从离群节点恢复

节点(node)

一个运行中的 Elasticsearch 实例称为一个 节点 ,而集群是由一个或者多个拥有相同 cluster.name 配置的节点组成, 它们共同承担数据和负载的压力。当有节点加入集群中或者从集群中移除节点时,集群将会重新平均分布所有的数据。

当一个节点被选举成为 主 节点(master)时, 它将负责管理集群范围内的所有变更 ,例如增加、删除索引,或者增加、删除节点等。 而 主节点并不需要涉及到文档级别的变更和搜索等操作 ,所以当集群只拥有一个主节点的情况下,即使流量的增加它也不会成为瓶颈。 任何节点都可以成为主节点。我们的示例集群就只有一个节点,所以它同时也成为了主节点。

作为用户, 我们可以将请求发送到 集群中的任何节点 ,包括主节点 。 每个节点都知道任意文档所处的位置,并且能够将我们的请求直接转发到存储我们所需文档的节点。 无论我们将请求发送到哪个节点,它都能负责从各个包含我们所需文档的节点收集回数据,并将最终结果返回給客户端。 Elasticsearch 对这一切的管理都是透明的。

分片(shard)

一个 分片 是一个底层的 工作单元 ,它仅保存了 全部数据中的一部分。

索引实际上是指向一个或者多个物理 分片 的 逻辑命名空间 。

文档被存储和索引到分片内,但是应用程序是直接与索引而不是与分片进行交互。

Elasticsearch 是利用分片将数据分发到集群内各处的。分片是数据的容器,文档保存在分片内,分片又被分配到集群内的各个节点里。 当你的集群规模扩大或者缩小时, Elasticsearch 会自动的在各节点中迁移分片,使得数据仍然均匀分布在集群里。

主分片(primary shard)

索引内任意一个文档都归属于一个主分片,所以主分片的数目决定着索引能够保存的最大数据量。

复制分片(副分片 replica shard)

一个副本分片只是一个主分片的拷贝。 副本分片作为硬件故障时保护数据不丢失的冗余备份,并为搜索和返回文档等读操作提供服务。

在索引建立的时候就已经确定了主分片数,但是副本分片数可以随时修改.

初始设置索引的分片方法

 PUT /blogs
{
   "settings" : {
      "number_of_shards" : 3,
      "number_of_replicas" : 1
   }
}
  
  • number_of_shards每个索引的主分片数,默认值是 5 。这个配置在索引创建后不能修改。
  • number_of_replicas每个主分片的副本数,默认值是 1 。对于活动的索引库,这个配置可以随时修改。

2 个节点

3 个节点

分片是一个功能完整的搜索引擎,它拥有使用一个节点上的所有资源的能力。 我们这个拥有6个分片(3个主分片和3个副本分片)的索引可以最大扩容到6个节点,每个节点上存在一个分片,并且每个分片拥有所在节点的全部资源。

修改复制分片数目的方法

 PUT /blogs/_settings
{
   "number_of_replicas" : 2
}  

拥有越多的副本分片时,也将拥有越高的吞吐量。

故障转移 failover

  • 选举新的主节点
  • 提升复制分片为主分片
  • 查看集群健康状态

     GET /_cluster/health
    
    {
       "cluster_name":          "elasticsearch",
       "status":                "green", 
       "timed_out":             false,
       "number_of_nodes":       1,
       "number_of_data_nodes":  1,
       "active_primary_shards": 0,
       "active_shards":         0,
       "relocating_shards":     0,
       "initializing_shards":   0,
       "unassigned_shards":     0
    }  

    status 字段指示着当前集群在总体上是否工作正常。它的三种颜色含义如下:

    • green所有的主分片和副本分片都正常运行。
    • yellow所有的主分片都正常运行,但不是所有的副本分片都正常运行。
    • red有主分片没能正常运行。

    当然Elasticsearch是一门水很深的技术,底层Lucene更为复杂,本文只是介绍了一下皮毛,后续可能会放出更多的相关知识技术,敬请关注。

    作者简介:Python菜鸟工程师,将在接下来的一段时间内与大家分享一些与Python相关的知识点。如若文中出现问题,各位大佬多多指点,互相学习。喜欢的关注一个吧!谢谢!

    文章来源:智云一二三科技

    文章标题:最受欢迎的企业搜索引擎Elasticsearch在Python中的应用

    文章地址:https://www.zhihuclub.com/201434.shtml

    关于作者: 智云科技

    热门文章

    网站地图