Elasticsearch学习

一 存储结构

在这里插入图片描述
首先存入的数据按index(必须小写)分为不同的文件,type代表了数据的类型方便读写,_id是唯一的,object可以是json。
基本概念可以看下链接2

  • 倒排索引 – 一般是id对用的内容这样子索引 倒排是吧数据分词后,记录每个词的所有id(实现时,Lucene将上面内容分别作为词典文件(TermDictionary)、频率文件(frequencies)、位置文件(positions)保存。其中词典文件不仅保存了每个关键词,还保留了指向频率文件和位置文件的指针,通过指针可以找到该关键字的频率信息和位置信息)
    每个index都有唯一的名称(必须小写)
    一个索引下只允许有一个类型
    存储的内容Object 也有field的,可以堪为关系行数据
  1. 而在我们elasticsearch中同一 Index 下,同名 Field 类型必须相同,即使不同的 Type;
  2. 同一 Index 下,TypeA 的 Field 会占用 TypeB 的资源(互相消耗资源),会形成一种稀疏存储的情况。尤其是 doc value ,为什么这么说呢?doc value为了性能考虑会保留一部分的磁盘空间,这意味着 TypeB 可能不需要这个字段的 doc_value 而 TypeA 需要,那么 TypeB 就被白白占用了一部分没有半点用处的资源;
  3. Score 评分机制是 index-wide 的,不同的type之间评分也会造成干扰。
  4. 索引元数据本身是放在主节点中维护的,同一个index中多个type,会涉及到大量字段变更及元数据变更的操作,都会导致该 Index 被堵塞或假死。我们应该对这样的 Index 做隔离,避免影响到其他 Index 正常的增删改查!
ES的设计精髓就是提高搜索效率

一般的es会为每个filed建立倒排索引,记录值所在的term id,值叫做term,对应的id列表叫做 Posting List
es为了提高搜索效率,对term进行排序,查找是二分查找提高了速度,这是 Term Dictionary
现在再看起来,似乎和传统数据库通过B-Tree的方式类似啊,为什么说比B-Tree的查询快呢?B-Tree通过减少磁盘寻道次数来提高查询性能,Elasticsearch也是采用同样的思路,直接通过内存查找term,不读磁盘,但是如果term太多,term dictionary也会很大,放内存不现实,于是有了Term Index,就像字典里的索引页一样,A开头的有哪些term,分别在哪页,可以理解为前缀树

联合索引

所以给定查询过滤条件 age=18 的过程就是先从 term index 找到 18 在 term dictionary 的大概位置,然后再从 term dictionary 里精确地找到 18 这个 term,然后得到一个 posting list 或者一个指向 posting list 位置的指针。然后再查询 gender= 女 的过程也是类似的。最后得出 age=18 AND gender= 女 就是把两个 posting list 做一个“与”的合并。

这个理论上的“与”合并的操作可不容易。对于 mysql 来说,如果你给 age 和 gender 两个字段都建立了索引,查询的时候只会选择其中最 selective 的来用,然后另外一个条件是在遍历行的过程中在内存中计算之后过滤掉。那么要如何才能联合使用两个索引呢?有两种办法:

  • 使用 skip list 数据结构。同时遍历 gender 和 age 的 posting list,互相 skip;
  • 使用 bitset 数据结构,对 gender 和 age 两个 filter 分别求出 bitset,对两个 bitset 做 AN 操作。

PostgreSQL 从 8.4 版本开始支持通过 bitmap 联合使用两个索引,就是利用了 bitset 数据结构来做到的。当然一些商业的关系型数据库也支持类似的联合索引的功能。Elasticsearch 支持以上两种的联合索引方式,如果查询的 filter 缓存到了内存中(以 bitset 的形式),那么合并就是两个 bitset 的 AND。如果查询的 filter 没有缓存,那么就用 skip list 的方式去遍历两个 on disk 的 posting list。

关于skip list 和 bitset 请参考 https://www.infoq.cn/article/database-timestamp-02/?utm_source=infoq&utm_medium=related_content_link&utm_campaign=relatedContent_articles_clk

二 搜索方法

  • GET logofesjson/log_of_es_json/18648169 ----GET _index/_type/_id 搜索指定索引类型下的id的内容
  • GET logofesjson/log_of_es_json/_search ----GET _index/_type/_search 搜索索引下的所有内容
1 Query-string 搜索通过命令非常方便地进行临时性的即席搜索
2 领域特定语言 (DSL), 指定了使用一个 JSON 请求
Documents APIs:

Single document APIs

  • Index API
  • Get API
  • Delete API
  • Update API

Multi-document APIs

  • Multi Get API
  • Bulk API
  • Delete By Query API
  • Update By Query API
  • Reindex API

更过查询语法可查看文档 https://www.elastic.co/guide/en/elasticsearch/reference/5.6/docs-reindex.html
elastic权威指南翻译版 https://es.xiaoleilu.com/index.html

  • match 模糊查询
  • match_phrase 较为精确的查询 比如world_1 world_2 match会当成两个词查 phrase会当成一个单词查

这是一个分页查询带排序的例子:

GET _index/_type/_search
{
  "from": 0, 
  "size": 20, 
  "query": {
    "bool": {
      "must": [{
        "match": {
          "FILED": "2019-06-28"
        }
      },
      {
        "match_phrase": {
          "FILED": "TEXT VAIL"
        }
      }]
    }
  },
"  _source":["filed1","filed2"],   //指定返回的字段  不指定返回所有
  "sort": [
    {
      "FILED": {
        "order": "asc"
      }
    }
  ]
}
查询和过滤

Query查询上下文:

在查询上下文中,查询会回答这个问题——“这个文档匹不匹配这个查询,它的相关度高么?”

如何验证匹配很好理解,如何计算相关度呢?之前说过,ES中索引的数据都会存储一个_score分值,分值越高就代表越匹配。另外关于某个搜索的分值计算还是很复杂的,因此也需要一定的时间。

查询上下文 是在 使用query进行查询时的执行环境,比如使用search的时候。

Filter过滤器上下文:

在过滤器上下文中,查询会回答这个问题——“这个文档匹不匹配?”

答案很简单,是或者不是。它不会去计算任何分值,也不会关心返回的排序问题,因此效率会高一点。

过滤上下文 是在使用filter参数时候的执行环境,比如在bool查询中使用Must_not或者filter。

另外,经常使用过滤器,ES会自动的缓存过滤器的内容,这对于查询来说,会提高很多性能。

总结

  1. 查询上下文中,查询操作不仅仅会进行查询,还会计算分值,用于确定相关度;在过滤器上下文中,查询操作仅判断是否满足查询条件

  2. 过滤器上下文中,查询的结果可以被缓存。

布尔查询 bool query

Bool查询现在包括四种子句,must,filter,should,must_not。

  • must 返回的文档必须满足must子句的条件,并且参与计算分值
  • filter 返回的文档必须满足filter子句的条件。但是不参与计算分值
  • should 返回的文档可能满足should子句的条件。在一个Bool查询中,如果没有must或者filter,有一个或者多个should子句,那么只要满足一个就可以返回。minimum_should_match参数定义了至少满足几个子句。
  • must_not 返回的文档必须不满足must_not定义的条件。
{
    "bool" : {
        "must" : {
            "term" : { "user" : "kimchy" }
        },
        "filter": {
            "term" : { "tag" : "tech" }
        },
        "must_not" : {
            "range" : {
                "age" : { "from" : 10, "to" : 20 }
            }
        },
        "should" : [
            {
                "term" : { "tag" : "wow" }
            },
            {
                "term" : { "tag" : "elasticsearch" }
            }
        ],
        "minimum_should_match" : 1,
        "boost" : 1.0
    }
}
constant_score

当我们不关心检索词频率TF(Term Frequency)对搜索结果排序的影响时,可以使用constant_score将查询语句query或者过滤语句filter包装起来。
检索词频率(TF):检索词在该字段出现的频率。出现频率越高,相关性也越高。字段中出现过5次要比只出现过1次的相关性高。
反向文档频率(IDF):每个检索词在索引中出现的频率。频率越高,相关性越低。 检索词出现在多数文档中会比出现在少数文档中的权重更低, 即检验一个检索词在文档中的普遍重要性。

boost

权重 - score受到协调因子boost的影响 score = score + boost

inner-hits

在使用搜索“has-child”搜索父文档时,一般情况只返回子文档符合条件的父文档。用 Inner-hits 则可以把父子文档同时返回——既返回父文档,也返回匹配has-child条件的子文档,相当于在父子之间join了。

adjust_pure_negative
  • q: What does “adjust_pure_negative” flag do?
  • a: You can ignore it. It “does the right thing” when calling Lucene when all clauses are “must_not” clauses (no shoulds or musts). Ordinarily Lucene expects some positive clauses so would return nothing. Elasticsearch adjusts for this case by adding a must match_all type clause which means Lucene would then provide results, filtered by the must_nots.
    True is the default setting and anything else seems non-sensical. --Elastic Team Member
    最简单你看到第一句话就知道可以忽略这个东西了。
Ignore Unmapped

When set to true the ignore_unmapped option will ignore an unmapped field and will not match any documents for this query. This can be useful when querying multiple indexes which might have different mappings. When set to false (the default value) the query will throw an exception if the field is not mapped. – Docs
当你把ignore_unmapped 设置为true时,会忽略掉没有匹配上的字段并且当前的query不会返回任何documents,再查询多个索引时可能会有多个结果时候比较有用,如果设置为false,没有匹配时会抛出异常。默认false。

term quey

term query不会分词,是精确查询。

QueryBuilders:
boolQuery:
    must:相当于sql的and
    must not:相当于sql的not
    should:相当于sql的or
mathcquery:单个匹配
mathcAllQuery:匹配所有
termQuery:termQuery("key", obj) 完全匹配 ;termsQuery("key", obj1, obj2..)  一次匹配多个值
multiMatchQuery:multiMatchQuery("text", "field1", "field2"..);  匹配多个字段, field有通配符忒行
idsQuery:构造一个只会匹配的特定数据 id 的查询
constantScoreQuery:看了一下这个类的构造函数ConstantScoreQuery(Filter filter) ,我的理解就是通过构造filter来完成文档的过滤,并且返回一个复合当前过滤条件的文档的常量分数,这个分数等于为查询条件设置的boost
fuzzyQuery:模糊查询
moreLikeThisQuery:文档中的文本查询
prefixQuery:前缀查询
rangeQuery:在一个范围内查询相匹配的文档
termQuery:一个查询相匹配的文件包含一个术语
termsQuery:一个查询相匹配的多个value---minimumMatch(1); // 设置最小数量的匹配提供了条件。默认为1。
wildcardQuery:通配符查询
nestedQuery:嵌套查询---scoreMode("total");// max, total, avg or none
disMaxQuery:对子查询的结果做union, score沿用子查询score的最大值,
spanFirstQuery:跨度查询,还包括(spanNearQuery,spanNotQuery,spanOrQuery,spanTermQuery)

三 数据管理

如果需要分批管理数据,比如日志多久删除一次,可以使用别名,建立新的索引关联到原有的索引上,并不对更新这个别名关系,旧的索引就可以在合适的时机删除.
先创建新的索引,在执行别名设置。移除旧的别名并添加新的别名。

PUT logofesjson_v2
{
  "mappings": {
    "log_of_es_json": {
      "properties": {
        "logId": {
          "type": "long"
        },
        "requestJson": {
          "type": "text",
          "index": false
        },
        "responseJson": {
          "type": "text",
          "index": false
        }
      }
    }
  },
  "index": {
    "number_of_shards": "5",
    "number_of_replicas": "1"
  }
}

POST  _aliases
{
  "actions": [
    {
      "remove": {
        "index": "logofesjson_v1",
        "alias": "logofesjson"
      }
    },
    {
      "add": {
        "index": "logofesjson_v2",
        "alias": "logofesjson"
      }
    }
  ]
}

关于分片 https://blog.csdn.net/alan_liuyue/article/details/79585345

数据的写入

Elasticsearch为了实现分布式,引入了shard,将segment分布在不同的机器上。并且根据_routing来决定如何分配到指定的shard。
Elasticsearch中每个index由多个shard组成,默认是5个,每个shard分布在不同的机器上。shard分为主分片和副本分片,在文档写入时,会根据_routing来计算(OperationRouting类)得出文档要写入哪个分片。这里的写入请求只会写主分片,当主分片写入成功后,会同时把写入请求发送给所有的副本分片,当副本分片写入成功后,会传回返回信息给主分片,主分片得到所有副本分片的返回信息后,再返回给客户端。
在写入时,我们可以在Request自己指定_routing,也可以在Mapping指定文档中的Field值作为_routing。如果没有指定_routing,则会把_id作为_routing进行计算。由于写入时,具有相同_routing的文档一定会分配在同一个分片上,所以如果是自定义的_routing,在查询时,一定要指定_routing进行查询,否则是查询不到文档的。这并不是局限性,恰恰相反,指定_routing的查询,性能上会好很多,因为指定_routing意味着直接去存储数据的shard上搜索,而不会搜索所有shard

从上述可以看出,Elasticsearch文档写入主要是写主分片和写副本分片。所以副本分片的个数就直接决定了写入的性能。合理配置副本数,在性能和安全之间取得平衡。

elastic实战系列 https://blog.csdn.net/xiaoyu_bd/article/details/81950081

文档

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你好!关于学习Elasticsearch,我可以给你一些指导。Elasticsearch是一个开源的分布式搜索和分析引擎,主要用于快速、实时地存储、搜索和分析大量数据。下面是一些学习Elasticsearch的步骤: 1. 了解基本概念:开始学习Elasticsearch之前,你需要了解一些基本的概念,比如索引(index)、类型(type)、文档(document)、字段(field)等。这将帮助你更好地理解Elasticsearch的工作原理。 2. 安装和配置:根据你的操作系统,你可以从Elasticsearch官方网站下载并安装合适的版本。安装完成后,你需要进行适当的配置,如设置集群名称、分配内存等。 3. 学习REST API:Elasticsearch提供了丰富的REST API,用于与其进行交互。了解如何使用这些API来索引、搜索和删除数据是学习Elasticsearch的重要一步。 4. 索引和搜索数据:学习如何创建索引、添加文档以及执行搜索操作是使用Elasticsearch的关键。掌握查询语法、过滤器、聚合操作等功能可以帮助你更有效地使用Elasticsearch。 5. 数据建模和分析:学习如何设计合适的数据模型和映射,以及如何使用Elasticsearch进行数据分析和可视化是提高你的技能的重要一步。 6. 扩展和优化:学习如何在生产环境中扩展和优化Elasticsearch集群是非常重要的。了解如何分片、复制、调优性能等将帮助你更好地管理和维护你的数据。 7. 学习资源:除了官方文档,还有很多优秀的学习资源可供参考,如书籍、教程和在线课程等。利用这些资源可以更系统地学习和掌握Elasticsearch。 希望这些步骤能对你学习Elasticsearch有所帮助!如果有任何问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值