ES 第二站 集群,recovery恢复,transport通信,模板Template,别名alias, 建议器 suggest , 路由routing , 打分机制 , 批量写入

ES 番外篇

ES 批量写入

  • 顺序写入 100条
# 写入 100条数据 

import time
from elasticsearch import Elasticsearch

es = Elasticsearch()

def timer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        print('共耗时约 {:.2f} 秒'.format(time.time() - start))
        return res
    return wrapper

@timer
def create_data():
    """ 写入数据 """
    for line in range(100):
        es.index(index='s2', doc_type='doc', body={'title': line})

if __name__ == '__main__':
    create_data()   # 执行结果大约耗时 7.79 秒
  • 批量写入 100条
#### 使用 es中 helper.bulk方法,批量写入
	# _index 对应索引的名称,且该索引必须是已存在的
	# _type 对应类型名称
    # _source 对应的字典内,每一篇文档的字段和值. 可能有多个字段
### 注意: 不能在内存中 一次行生成很大的内存数据,采用生成器的方法去生成
import time
from elasticsearch import Elasticsearch
from elasticsearch import helpers

es = Elasticsearch()

def timer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        print('共耗时约 {:.2f} 秒'.format(time.time() - start))
        return res

    return wrapper

@timer
def create_data():
    """ 写入数据 """
    for line in range(100):
        es.index(index='s2', doc_type='doc', body={'title': line})

@timer
def batch_data():
    """ 批量写入数据 """
    action = [{
        "_index": "s2",
        "_type": "doc",
        "_source": {
            "title": i
        }
    } for i in range(10000000)]
    helpers.bulk(es, action)


if __name__ == '__main__':
    # create_data()
    batch_data()  # MemoryError
# 使用生成器,批量写入
import time
from elasticsearch import Elasticsearch
from elasticsearch import helpers

es = Elasticsearch()

def timer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        print('共耗时约 {:.2f} 秒'.format(time.time() - start))
        return res

    return wrapper

@timer
def gen():
    """ 使用生成器批量写入数据 """
    action = ({
        "_index": "s2",
        "_type": "doc",
        "_source": {
            "title": i
        }
    } for i in range(100000))
    helpers.bulk(es, action)

if __name__ == '__main__':
    gen()

总结: 使用 生成器写入数据,python操作es的资源远远小于 es的jvm虚拟机使用的资源

ES的4种建议器

​ 说明: 建议器具有纠错和查询的功能

_suggest 建议查询
# _suggest 已经弃用
PUT s1
{
  "mappings": {
    "doc": {
      "properties": {
        "title": {
          "type": "text",
          "analyzer": "standard"
        }
      }
    }
  }
}

PUT s1/doc/1
{
  "title": "Lucene is cool"
}

PUT s1/doc/2
{
  "title":"Elasticsearch builds on top of lucene"
}

GET s1/doc/_search
{
  "query": {
    "match": {
      "title": "Lucene"
    }
  },
  "suggest": {
    "my_suggest": {
      "text": "Elasticsear lucen",
      "term": {
        "field": "title"
      }
    }
  }
}

#### 结果:
{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 0.2876821,
    "hits" : [
      {
        "_index" : "s1",
        "_type" : "doc",
        "_id" : "2",
        "_score" : 0.2876821,
        "_source" : {
          "title" : "Elasticsearch builds on top of lucene"
        }
      },
      {
        "_index" : "s1",
        "_type" : "doc",
        "_id" : "1",
        "_score" : 0.2876821,
        "_source" : {
          "title" : "Lucene is cool"
        }
      }
    ]
  },
  "suggest" : {
    "my_suggest" : [
      {
        "text" : "elasticsear",
        "offset" : 0,
        "length" : 11,
        "options" : [
          {
            "text" : "elasticsearch",
            "score" : 0.8181818,
            "freq" : 1
          }
        ]
      },
      {
        "text" : "lucen",
        "offset" : 12,
        "length" : 5,
        "options" : [
          {
            "text" : "lucene",
            "score" : 0.8,
            "freq" : 2
          }
        ]
      }
    ]
  }
}

### 总结 
	1. 已经将我们的建议查询的字段值,查了出来.放在 options内
	2. 可以使用多个_sugget建议器,但名字要不一样
词条建议器 term suggester
# 对于给定文本的每个词条, 从索引中抽取要建议的关键词. 对于短字段(分类或标签)很有效
# 准备索引和数据
PUT s2
{
  "mappings": {
    "doc": {
      "properties": {
        "title": {
          "type": "text",
          "analyzer": "standard"
        }
      }
    }
  }
}

PUT s2/doc/1
{
  "title": "Lucene is cool"
}

PUT s2/doc/2
{
  "title": "Elasticsearch builds on top of lucene"
}

PUT s2/doc/3
{
  "title": "Elasticsearch rocks"
}

PUT s2/doc/4
{
  "title": "Elastic is the company behind ELK stack"
}

PUT s2/doc/5
{
  "title": "elk rocks"
}
PUT s2/doc/6
{
  "title": "elasticsearch is rock solid"
}

### 建议器 示例
GET s2/doc/_search
{
  "suggest": {
    "my_suggest": {
      "text": "luenc",
      "term": {
        "field": "title"
      }
    }
  }
}

# 结果

{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 0,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "suggest" : {
    "my_suggest" : [
      {
        "text" : "luenc",
        "offset" : 0,
        "length" : 5,
        "options" : [
          {
            "text" : "lucene",
            "score" : 0.6,
            "freq" : 2
          }
        ]
      }
    ]
  }
}



term 建议器中的字段

- text :建议文本,必须字段. (可通过全局多个建议器中查询相同的内容)或按照单个建议器的格式来
    
- field: 从field字段中获取候选建议的字段。这是一个必需的选项,需要全局设置或根据建议设置
    
- analyzer:用于分析建议文本的分析器。默认为建议字段的搜索分析器。

- size:个建议文本标记返回的最大条目。

- sort:定义如何根据建议文本术语对建议进行 `排序` 。它有两个可能的值。
		- score,先按分数排序,然后按文档频率排序,再按术语本身排序。
		- frequency,首先按文档频率排序,然后按相似性分数排序,然后按术语本身排序。也可以理解为按照流行度排序。
        
- suggest_mode:控制建议的模式,有3个模式可选择。
		- missing,仅为不在索引中的建议文本术语提供建议。这是默认值。
		- popular,仅建议在比原始建议文本术语更多的文档中出现的建议。也就是说提供比原有输入词频更高的词条
		- always,根据建议文本中的条款建议任何匹配的建议。说白了就是无论如何都会提供建议。
        
- lowercase_terms:在文本分析之后降低建议文本术语的大小写。

- min_word_length:建议文本术语必须具有的最小长度才能包含在内。默认为4.(旧名称min_word_len已弃用)。

- shard_size:设置从每个单独分片中检索的最大建议数。在减少阶段,仅根据size选项返回前N个建议。默认为该 size选项。将此值设置为高于该值的值size可能非常有用,以便以性能为代价获得更准确的拼写更正文档频率。由于术语在分片之间被划分,因此拼写校正频率的分片级文档可能不准确。增加这些将使这些文档频率更精确

- max_inspections:用于乘以的因子, shards_size以便在碎片级别上检查更多候选拼写更正。可以以性能为代价提高准确性。默认为5。

- string_distance:用于比较类似建议术语的字符串距离实现。
	- nternal,默认值基于damerau_levenshtein,但高度优化用于比较索引中术语的字符串距离。
    - damerau_levenshtein,基于Damerau-Levenshtein算法的字符串距离算法。
    - levenshtein,基于Levenshtein编辑距离算法的字符串距离算法。
    - jaro_winkler,基于Jaro-Winkler算法的字符串距离算法。
    - ngram,基于字符n-gram的字符串距离算法。

词条建议器是如何运作的

词条建议器使用了Lucene的 `错拼检查器模块`,该模块会根据给定词条的 `编辑距离` (es使用了叫做Levenstein edit distance的算法,其核心思想就是一个词改动多少字符就可以和另外一个词一致)

从索引中返回最大编辑距离不超过某个值的那些词条。比如说为了从mik得到mick,需要加入一个字母(也就是说需要至少要改动一次),所以这两个词的编辑距离就是1。我们可以通过配置一系列的选项,来均衡灵活和性能:

	- max_edits:最大编辑距离候选建议可以具有以便被视为建议。只能是介于1和2之间的值。任何其他值都会导致抛出错误的请求错误。默认为2。

    - prefix_length:必须匹配的最小前缀字符的数量才是候选建议。默认为1.增加此数字可提高拼写检查性能。通常拼写错误不会出现在术语的开头。(旧名prefix_len已弃用)。

    - min_doc_freq:建议应出现的文档数量的最小阈值。可以指定为绝对数字或文档数量的相对百分比。这可以仅通过建议高频项来提高质量。默认为0f且未启用。如果指定的值大于1,则该数字不能是小数。分片级文档频率用于此选项。

    - max_term_freq:建议文本令牌可以存在的文档数量的最大阈值,以便包括在内。可以是表示文档频率的相对百分比数(例如0.4)或绝对数。如果指定的值大于1,则不能指定小数。默认为0.01f。这可用于排除高频术语的拼写检查。高频术语通常拼写正确,这也提高了拼写检查的性能。分片级文档频率用于此选项。

词组建议器 phrase suggester

# 词条建议器的扩展, 为整个文本(而不是单个词条)提供建议方案. 考虑了各个词条彼此临近出现的频率,使的该建议器更适合较长的字段. 例如商品描述
# 1. 数据准备 
PUT s4
{
  "mappings": {
    "doc": {
      "properties": {
        "title": {
          "type": "text",
          "analyzer": "standard"
        }
      }
    }
  }
}

PUT s4/doc/1
{
  "title": "Lucene is cool"
}

PUT s4/doc/2
{
  "title": "Elasticsearch builds on top of lucene"
}

PUT s4/doc/3
{
  "title": "Elasticsearch rocks"
}

PUT s4/doc/4
{
  "title": "Elastic is the company behind ELK stack"
}

PUT s4/doc/5
{
  "title": "elk rocks"
}

PUT s4/doc/6
{
  "title": "elasticsearch is rock solid"
}

# 2.  phrase 建议器
GET s4/doc/_search
{
  "suggest": {
    "my_s4": {
      "text": "lucne and elasticsear rock",
      "phrase": {
        "field": "title"
      }
    }
  }
}

# 3. 结果
{
  "took" : 6,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 0,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "suggest" : {
    "my_s4" : [
      {
        "text" : "lucne and elasticsear rock",
        "offset" : 0,
        "length" : 26,
        "options" : [
          {
            "text" : "lucne and elasticsearch rocks",
            "score" : 0.12709484
          },
          {
            "text" : "lucne and elasticsearch rock",
            "score" : 0.10422645
          },
          {
            "text" : "lucne and elasticsear rocks",
            "score" : 0.10036137
          }
        ]
      }
    ]
  }
}

# 4. 高亮查询
GET s4/doc/_search
{
  "suggest": {
    "my_s4": {
      "text": "lucne and elasticsear rock",
      "phrase": {
        "field": "title",
        "highlight":{
          "pre_tag":"<em>",
          "post_tag":"</em>"
        }
      }
    }
  }
}
# 5. 高亮结果
GET s4/doc/_search
{
  "suggest": {
    "my_s4": {
      "text": "lucne and elasticsear rock",
      "phrase": {
        "field": "title",
        "highlight":{
          "pre_tag":"<b id='d1' class='t1' style='color:red;font-size:18px;'>",
          "post_tag":"</b>"
        }
      }
    }
  }
}
完成建议器 completion suggester
# 该建议器根据词条的前缀,提供建议(类似最左前缀查询的意思). 该建议器是在内存中工作的,速度要比之前说的match_phrase_prefix快很多
https://www.cnblogs.com/Neeo/articles/10695019.html
上下文建议器context suggester
# 该建议器是完成建议器的扩展,允许我们根据词条或分类亦或是地理位置信息进行过滤
https://www.cnblogs.com/Neeo/articles/10695031.html
建议器 全部 CNB:
https://www.cnblogs.com/Neeo/articles/10694922.html

ES集群

https://www.cnblogs.com/Neeo/articles/10570016.html

ES的transport通信机制

transport是集群间通信的基础,它有两种实现:
	- localtransport,主要用于jvm中的节点通信,因为在同一个jvm上的网络模拟,localtransport的实现也相对简单,但实际用处在es中有限。
	- nettytransport,一种基于netty实现的transport,同样用于节点间的通信。
https://www.cnblogs.com/Neeo/articles/10943474.html

ES的Recovery恢复

### 什么是 recovery?
在elasticsearch中,recovery指的是一个索引的分片分配到另外一个节点的过程,一般在快照恢复、索引复制分片的变更、节点故障或重启时发生,由于master节点保存整个集群相关的状态信息,因此可以判断哪些分片需要再分配及分配到哪个节点,例如:

	- 如果某个主分片在,而复制分片所在的节点挂掉了,那么master需要另行选择一个可用节点,将这个主分片的复制分片分配到可用节点上,然后进行主从分片的数据复制。
如果某个主分片所在的节点挂掉了,复制分片还在,那么master会主导将复制分片升级为主分片,然后再做主从分片数据复制。
	- 如果某个分片的主副分片都挂掉了,则暂时无法恢复,而是要等持有相关数据的节点重新加入集群后,master才能主持数据恢复相关操作。

路由routing

# 作用: 通过路由搜索,提高搜索效率
https://www.cnblogs.com/Neeo/articles/10869556.html

打分机制TF-IDF

TF  词频
IDF 逆文档频率
https://www.cnblogs.com/Neeo/articles/10721071.html

ES的模版

elasticsearch很大一部分工作是用来处理日志信息的,比如某公司对于日志处理策略是以日期为名创建每天的日志索引。并且每天的索引映射类型和配置信息都是一样的,只是索引名称改变了。如果手动的创建每天的索引,将会是一件很麻烦的事情。为了解决类似问题,elasticsearch提供了预先定义的模板进行索引创建,这个模板称作为Index Templates。通过索引模板可以让类似的索引重用同一个模板。
https://www.cnblogs.com/Neeo/articles/10869231.html

别名使用

### 别名 就像 软连接一样
### 别名能解决的问题
    1. 在运行的集群中可以无缝的从一个索引切换到另一个索引。
    2. 可以给多个索引分组。
    3. 给索引的一个子集创建视图,没错我们可以简单将es中的索引理解为关系型数据库中的视图。
    4. 可以与路由搭配使用。xxxxxxxxxx4 11. 快速查询 , 多个索引指向一个别名在运行的集群中可以无缝的从一个索引切换到另一个索引。2可以给多个索引分组。3给索引的一个子集创建视图,没错我们可以简单将es中的索引理解为关系型数据库中的视图。4可以与路由搭配使用。
https://www.cnblogs.com/Neeo/articles/10897280.html
原文地址:https://www.cnblogs.com/dengz/p/14800729.html