1 简介概念

1.1 索引(index)

一个索引就是一个拥有几分相似特征的文档的集合。比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单 数据的索引。一个索引由一个名 字来标识(必须全部是小写字母的),并且当我们要对对应于这个索引中的文档进行索引、搜索、 更新和删除的时候,都要使用到这个名字。 在一个集群中,如果你想,可以定义任意多的索引。可以类比于mysql中的database。

1.2 类型(type)

在一个索引中,你可以定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类/分区,其语义完全由你来定。通常,会为具有一组共同字段的文档定义一个 类型。比如说,我们假设你运营一个博客平台并且将你所有的数据存储到一个索引中。在这个索引中,你可以为用户数据定义一个类型,为博客数据定义另一个类 型,当然,也可以为评论数据定义另一个类型。为了方便理解,可以类比于mysql中的table,但又不完全一样。

1.3 文档(document)

一个文档是一个可被索引的基础信息单元。比如,你可以拥有某一个客户的文档,某一个产品的一个文档,当然,也可以拥有某个订单的一个文档。文档以 JSON(Javascript Object Notation)格式来表示,而JSON是一个到处存在的互联网数据交互格式。 在一个index/type里面,只要你想,你可以存储任意多的文档。注意,尽管一个文档,物理上存在于一个索引之中,文档必须被索引/赋予一个索引的type。为了方便理解可以类比于mysql中的一条记录。

1.3.1 文档元数据

一个文档不只有数据。它还包含了元数据(metadata)——关于文档的信息。三个必须的元数据节点是:

节点 说明
_index 文档存储的地方
_type 文档代表的对象的类
_id 文档的唯一标识

1.3.1.1 _index

索引(index)类似于关系型数据库里的“数据库”——它是我们存储和索引关联数据的地方。 提示:

事实上,我们的数据被存储和索引在分片(shards)中,索引只是一个把一个或多个分片分组在一起的逻辑空间。然而,这只是一些内部细节——我们的程序完全不用关心分片。对于我们的程序而言,文档存储在索引(index)中。剩下的细节由Elasticsearch关心既可。 我们将会在《索引管理》章节中探讨如何创建并管理索引,但现在,我们将让Elasticsearch为我们创建索引。我们唯一需要做的仅仅是选择一个索引名。这个名字必须是全部小写,不能以下划线开头,不能包含逗号。让我们使用website做为索引名。

1.3.1.2 _type

在应用中,我们使用对象表示一些“事物”,例如一个用户、一篇博客、一个评论,或者一封邮件。每个对象都属于一个类(class),这个类定义了属性或与对象关联的数据。user类的对象可能包含姓名、性别、年龄和Email地址。1

在关系型数据库中,我们经常将相同类的对象存储在一个表里,因为它们有着相同的结构。同理,在Elasticsearch中,我们使用相同类型(type)的文档表示相同的“事物”,因为他们的数据结构也是相同的。 每个类型(type)都有自己的映射(mapping)或者结构定义,就像传统数据库表中的列一样。所有类型下的文档被存储在同一个索引下,但是类型的映射(mapping)会告诉Elasticsearch不同的文档如何被索引。 我们将会在《映射》章节探讨如何定义和管理映射,但是现在我们将依赖Elasticsearch去自动处理数据结构。

_type的名字可以是大写或小写,不能包含下划线或逗号。我们将使用blog做为类型名。

1.3.1.3 _id

id仅仅是一个字符串,它与_index和_type组合时,就可以在Elasticsearch中唯一标识一个文档。当创建一个文档,你可以自定义_id,也可以让Elasticsearch帮你自动生成。

字段(field)

通过一组field,描述一个document的schema。field包含类型,使用的分词器,相关性评分开关等属性。 相关控制度(score)

对于仅处理结构化数据(比如日期,数值和字符枚举值)的数据库,它们只需要检查一份文档(在关系数据库中是一行)是否匹配查询即可。但是对于非结构化数据,我们在做检索的时候,需要根据匹配程度,进行排序。es利用全文搜索相关度的公式,或者被称为相似度算法,将多个因素综合起来为每份文档产生一个相关度_score。定义index的mapping时,需要为每个field设置这个值。

2 路由

当你索引一个文档,它被存储在单独一个主分片上。Elasticsearch是如何知道文档属于哪个分片的呢?当你创建一个新文档,它是如何知道是应该存储在分片1还是分片2上的呢?

进程不能是随机的,因为我们将来要检索文档。事实上,它根据一个简单的算法决定:

shard = hash(routing) % number_of_primary_shards

routing值是一个任意字符串,它默认是_id但也可以自定义。这个routing字符串通过哈希函数生成一个数字,然后除以主切片的数量得到一个余数(remainder),余数的范围永远是0到number_of_primary_shards - 1,这个数字就是特定文档所在的分片。 这也解释了为什么主分片的数量只能在创建索引时定义且不能修改:如果主分片的数量在未来改变了,所有先前的路由值就失效了,文档也就永远找不到了。

有时用户认为固定数量的主分片会让之后的扩展变得很困难。现实中,有些技术会在你需要的时候让扩展变得容易。我们将在《扩展》章节讨论。

所有的文档API(get、index、delete、bulk、update、mget)都接收一个routing参数,它用来自定义文档到分片的映射。自定义路由值可以确保所有相关文档——例如属于同一个人的文档——被保存在同一分片上。我们将在《扩展》章节说明你为什么需要这么做。

FAQ

  1. 分页问题?
  2. 什么时候用filter,什么时候用query?其实两个功能一样,只有需要评分的时候才需要使用query。其他情况使用filter
  3. bool 和and查询。bool代替了and
  4. 深分页?足够大的from值会把es拖垮
  5. 结果抖动。针对分布式场景按照timestamp字段来对你的结果排序,并且有两个document有相同的timestamp。由于搜索请求是在所有有效的分片副本间轮询的,这两个document可能在原始分片里是一种顺序,在副本分片里是另一种顺序。这就是被称为结果震荡(bouncing results)的问题:用户每次刷新页面,结果顺序会发生变化。避免这个问题方法是对于同一个用户总是使用同一个分片。方法就是使用一个随机字符串例如用户的会话ID(session ID)来设置preference参数。
  6. 超时

    查询概念

    elasticsearch的查询有两部分组成:query and filter。两者的主要区别在于:filter是不计算相关性的,同时可以cache。因此,filter速度要快于query。

Query

主要是查询,一般来说分为全部字段查询和单个字段查询,也就是match_all和field查询。一般来说match_all性能比较低需要遍历所有field,一般来说最好指定field查询。Query又可以分为下面几类:

1 term查询

基于词条的查询,也就是分词,这样讲比较模糊,比如一个英文句子 i am boy,按照分词后大概会分为这样[i,am,boy],如果通过term查询查询,只能输入 am、i、boy这几个单词能够搜索到这条数据。如果想直接通过bo能够搜索到这条数据,是无法做到的

2 wildcard查询

wildcard查询和prefix查询类似,也是一个基于词条的低级别查询。但是它能够让你指定一个模式(Pattern),而不是一个前缀(Prefix)。它使用标准的shell通配符:?用来匹配任意字符,*用来匹配零个或者多个字符。例如这样的:W[0-9].+ 查询数组,也就是正则查询吧

3 prefix查询

prefix查询使用起来跟like差不多,只不过是前缀查询,比如like 'bo%'属于前缀匹配

4 fuzzy查询

模糊搜索,这个比较模糊的一种查询,这种方式主要是一种模糊度的查询,如果文档中存在 确切 包含于用户查询的内容,它们应该出现在结果集的前面, 但更弱的匹配可能在下面的列表中.如果没有精确匹配的文档, 至少我们应该为用户显示可能的匹配结果; 它们甚至有可能就是用户原来想要的,就类似现在的搜索引擎,尝试后发现对中文的支持不太好

5 range查询

区间查询,比如说查询0到100之间这类的查询。都可以使用range查询,常用的时间格式在es中存储格式是数字类型,一般查询时间区间的时候可以用range查询

6 query_string查询

7 text查询

8 missing查询

results matching ""

    No results matching ""