查询优化

1 从提高查询精确度进行优化:

 本部分主要针对全文搜索进行探究。

1.1 倒排索引

1.1.1 什么是倒排索引:

一个倒排索引由文档中所有不重复词的列表构成,对于其中每个词,有一个包含它的文档列表。

倒排索引的好处:

当输入一些关键词进行匹配时,包含关键词越多的文档,得分越高,即,相关度越大。

如何建立倒排索引:

好像ES会为所有精确值字段全文字段分词后的词条自动创建倒排索引。

1.2 分析

1.2.1 什么是分析:

分析包括两部分,分词标准化。

什么是分词:

将字符串切分成词条的过程,是我们为全文搜索添加倒排索引必不可少的一步。

什么是标准化:

比如说:

对计算机而言"diane"和"Diane"是两个不同的词。因此,如果不进行标准化,在我们的倒序索引中将会为"diane"和"Diane"分别制作文档列表。假如此时我想要搜索包含"Diane"的文档,但我的查询语句中输入的是"diane"。这个时候,只会匹配包含"diane"的文档,而绝大多数包含正确拼写的"Diane"的文档将不被匹配。我们希望,不管用户输入的是"diane"还是"Diane",所有包含"diane"或"Diane"的文档都能被匹配。这时候,我们需要先对文档进行标准化处理,将"Diane"词条标准化为"diane",所有包含"diane"或"Diane"的文档都对应到"diane"词条的文档列表。而在查询的时候,同样要对查询关键字进行标准化,使得不论用户输入的是"diane"还是"Diane",计算匹配度时,都在“diane”词条的文档列表中进行搜索。

除了处理大小写,标准化还有许多其他处理能力。

1.2.2 如何分析?——分析器

ES中带有一些现成的分析器,但想要达到特定的目标,一般要创建自定义分析器

一个 分析器 就是在一个包里面组合了三种功能的一个包装器, 三种功能按照顺序被执行:

字符过滤器:用来整理一个尚未被分词的字符串。例如:使用 html清除 来移除掉HTML文件中所有的HTML标签。一个分析器可以0或多个字符过滤器。

分词器:一个分析器必须有一个唯一的分词器。

词单元过滤器:可以修改、添加或者移除词单元。如:lowercase stop

1.2.3 如何创建分析器:

本部分内容较多,转至Elasticsearch自定义分析器。

2 从响应速度的角度进行优化:

1. Routing参数

当执行查询时,查询会传播到各个shard(在replica之间轮询)。如何指定在哪些shard上进行查询呢?这可以通过routing参数控制。

demo:

插入数据时,添加routing参数。这里我们希望在查询的时候,只在某个user(kimchy)的tweet中进行搜索。

POST /twitter/tweet?routing=kimchy
{
  "user":"kimchy",
  "postDate":"2009-11-15T14:12:12",
  "message":"trying out Elasticsearch"
}


查询时,指定routing为kimchy,就能只在相关的shard中进行搜索。

POST /twitter/_search?routing=kimchy
{
    "query": {
        "bool" : {
            "must" : {
                "query_string" : {
                    "query" : "out"
                }
            },
            "filter" : {
                "term" : { "user" : "kimchy" }
            }
        }
    }
}

# 返回结果:
{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 0.2876821,
    "hits": [
      {
        "_index": "twitter",
        "_type": "tweet",
        "_id": "7tU6HmIBPZfz2v0D3QAm",
        "_score": 0.2876821,
        "_routing": "kimchy",
        "_source": {
          "user": "kimchy",
          "postDate": "2009-11-15T14:12:12",
          "message": "trying out Elasticsearch"
        }
      }
    ]
  }
}



搜索

文档中的每个字段都将被索引并且可以被查询。

全文检索,找出所有匹配关键字的文档并按照相关性(relevance) 排序后返回结果。

映射(Mapping) 描述数据在每个字段内如何存储。映射定义了类型中的,每个数据类型,以及Elasticsearch如何处理这些域。映射也用于配置与类型有关的元数据。

对字符串域,可以通过index属性控制是否索引、分析该域;通过analyser属性控制如何分析该域。

分析(Analysis) 全文是如何处理使之可以被搜索的

领域特定查询语言(Query DSL) Elasticsearch 中强大灵活的查询语言

_score :查询结果中的_score衡量了文档与查询的匹配程度。默认情况下,首先返回最相关的文档结果,就是说,返回的文档是按照 _score 降序排列的。

如果不对某一特殊的索引或者类型做限制,就会搜索集群中的所有文档。因而,若想在一个或多个特定的索引并且在一个或者多个特定的类型中进行搜索。我们可以通过在URL中指定特定的索引和类型达到这种效果。

例如:

/_search 
在所有的索引中搜索所有的类型 
/gb/_search 
在 gb 索引中搜索所有的类型 
/gb,us/_search 
在 gb 和 us 索引中搜索所有的文档 
/g*,u*/_search 
在任何以 g 或者 u 开头的索引中搜索所有的类型 
/gb/user/_search 
在 gb 索引中搜索 user 类型 
/gb,us/user,tweet/_search 
在 gb 和 us 索引中搜索 user 和 tweet 类型 
/_all/user,tweet/_search 
在所有的索引中搜索 user 和 tweet 类型



_all:当索引一个文档的时候,Elasticsearch 取出所有字段的值拼接成一个大的字符串,作为 _all 字段进行索引。搜索时,若没有指定域,则在_all中进行搜索。

例如,有如下文档:

{
    "tweet":    "However did I manage before Elasticsearch?",
    "date":     "2014-09-14",
    "name":     "Mary Jones",
    "user_id":  1
}


执行:

GET /_search?q=mary


这就好似增加了一个名叫 _all 的额外字段:

"However did I manage before Elasticsearch? 2014-09-14 Mary Jones 1"


除非设置特定字段,否则查询字符串就使用 _all 字段进行搜索。

(在刚开始开发一个应用时,_all 字段是一个很实用的特性。之后,你会发现如果搜索时用指定字段来代替 _all 字段,将会更好控制搜索结果。当 _all 字段不再有用的时候,可以将它置为失效,正如在 元数据: _all 字段 中所解释的。)



Elasticsearch 中的数据可以概括的分为两类:精确值和全文。(字符串域视为全文或精确值字符串)


倒排索引

为文档中的某个域建立倒排索引,就是

1. 得出set(将所有文档中这个域里的token)

2. 对1中得到的每个token,获得出现过该token的文档列表

 注意:在进行倒排索引前,需要对token进行标准化处理,使得同义词、同词根的词、大小写不一样的词分别映射给同一个词。同样,要对搜索字符串进行相同的标准化处理。

分词和标准化的过程称为分析

分析器:

1. 自定义分析器

Elasticsearch提供了开箱即用的字符过滤器分词器token 过滤器。这些可以组合起来形成自定义的分析器以用于不同的目的

2. 内置分析器

 

类型 在 Elasticsearch 中表示一类相似的文档。 类型由名称映射(相当于数据库中的 schema)组成。

 

 

 

 

全文搜索查询优化

1 基于词项与基于全文

文本查询可以划分成两大家族:

1.1 基于词项的查询

 

1.2 基于全文的查询

 

报错及处理

:"The bulk request must be terminated by a newline [\n]"

只要将json文件末尾加上一个回车键,得到一个新的空行,保存退出,重新在cmd中执行批量插入代码即可。样例

其他

因为:

POST   /uri     创建

PUT    /uri/xxx 更新或创建

所以在创建一个没有指定Id的文件时,要用post而不是put