Elasticsearch 搜索
Posted 为什么人的眼睛有黑白两色
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Elasticsearch 搜索相关的知识,希望对你有一定的参考价值。
映射(Mapping)描述数据在每个字段内如何存储 分析(Analysis)全文是如何处理使之可以被搜索的 领域特定查询语言(Query DSL)Elasticsearch 中强大灵活的查询语言
如果低响应时间比完成结果更重要,你可以指定 timeout
为 10 或者 10ms(10毫秒),或者 1s(1秒): timeout
不是停止执行查询,它仅仅是告知正在协调的节点返回到目前为止收集的结果并且关闭连接。在后台,其他的分片可能仍在执行查询即使是结果已经被发送了。使用超时是因为 SLA(服务等级协议)对你是很重要的,而不是因为想去中止长时间运行的查询。
GET /_search?timeout=10ms
{ "hits" : { "total" : 14, --总文档数 "hits" : [ { "_index": "us", --索引名称 "_type": "tweet", "_id": "7", "_score": 1, --匹配度 "_source": { "date": "2014-09-17", "name": "John Smith", "tweet": "The Query DSL is really powerful and flexible", "user_id": 2 } }, ... 9 RESULTS REMOVED ... ], "max_score" : 1 }, "took" : 4, --耗费的时间 "_shards" : { --分片 "failed" : 0, "successful" : 10, "total" : 10 }, "timed_out" : false --超时 }/_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
类型
分页,Elasticsearch 接受from
和size
参数,一个请求经常跨越多个分片,每个分片都产生自己的排序结果,这些结果需要进行集中排序以保证整体顺序是正确的。:GET /_search?size=5&from=10
size
- 显示应该返回的结果数量,默认是
10
from
- 显示应该跳过的初始结果数量,默认是
0
- 由于映射字段的类型不同会导致查询结果不一样,_all默认为string类型,注意Elasticsearch 中的数据可以概括的分为两类:精确值和全文。
- Elasticsearch 使用一种称为 倒排索引 的结构,它适用于快速的全文搜索。一个倒排索引由文档中所有不重复词的列表构成,对于其中每个词,有一个包含它的文档列表。为了创建倒排索引,我们首先将每个文档的
content
域拆分成单独的 词(我们称它为词条
或tokens
),创建一个包含所有不重复词条的排序列表,然后列出每个词条出现在哪个文档。 - 分词和标准化的过程称为 分析,可以使用自定义映射来使用特定的分析器
-
- 首先,将一块文本分成适合于倒排索引的独立的 词条 ,
- 之后,将这些词条统一化为标准格式以提高它们的“可搜索性”,或者 recall
分析器执行上面的工作。 分析器 实际上是将三个功能封装到了一个包里:
- 字符过滤器
- 首先,字符串按顺序通过每个 字符过滤器 。他们的任务是在分词前整理字符串。一个字符过滤器可以用来去掉html,或者将
&
转化成 `and`。 - 分词器
- 其次,字符串被 分词器 分为单个的词条。一个简单的分词器遇到空格和标点的时候,可能会将文本拆分成词条。
- Token 过滤器
- 最后,词条按顺序通过每个 token 过滤器 。这个过程可能会改变词条(例如,小写化
Quick
),删除词条(例如, 像a`, `and`, `the
等无用词),或者增加词条(例如,像jump
和leap
这种同义词)。
Elasticsearch提供了开箱即用的字符过滤器、分词器和token 过滤器。当你查询一个 全文 域时, 会对查询字符串应用相同的分析器,以产生正确的搜索词条列表。当你查询一个 精确值 域时,不会分析查询字符串, 而是搜索你指定的精确值。
Text to analyze
{ -
"tokens": [ { "token": "text", --实际存储到索引中的词条 "start_offset": 0, --字符在原始字符串中的位置 "end_offset": 4,--字符在原始字符串中的位置
"type": "<ALPHANUM>", "position": 1 --指明词条在原始文本中出现的位置 }
]
}
时间域视为时间,数字域视为数字,字符串域视为全文或精确值字符串, Elasticsearch 需要知道每个域中数据的类型。这个信息包含在映射中。string
域映射的两个最重要 属性是index
和analyzer
。空域不会被索引analyzed
- 首先分析字符串,然后索引它。换句话说,以全文索引这个域。
not_analyzed
- 索引这个域,所以它能够被搜索,但索引的是精确值。不会对它进行分析。
no
- 不索引这个域。这个域不会被搜索到。
-
{ "tag": { "type": "string", "index": "not_analyzed"
"analyzer": "english"--指定分析器} }
{ "gb": { "tweet": { --根对象
"properties": { "tweet": { "type": "string" }, "user": { --内部对象
"type": "object", "properties": { "id": { "type": "string" }, "gender": { "type": "string" }, "age": { "type": "long" }, "name": { --内部对象
"type": "object", "properties": { "full": { "type": "string" }, "first": { "type": "string" }, "last": { "type": "string" } } } } } } } } }
内部域 可以通过名称引用(例如,first
)。为了区分同名的两个域,我们可以使用全 路径 (例如,user.name.first
) 或type
名加路径(tweet.user.name.first
)。search
API 同时支持 GET、POST
请求.自 Elasticsearch 问世以来,查询与过滤(queries and filters)就独自成为 Elasticsearch 的组件。但从 Elasticsearch 2.0 开始,过滤(filters)已经从技术上被排除了,同时所有的查询(queries)拥有变成不评分查询的能力。
过滤查询(Filtering queries)只是简单的检查包含或者排除,这就使得计算起来非常快。考虑到至少有一个过滤查询(filtering query)的结果是 “稀少的”(很少匹配的文档),并且经常使用不评分查询(non-scoring queries),结果会被缓存到内存中以便快速读取,所以有各种各样的手段来优化查询结果。
相反,评分查询(scoring queries)不仅仅要找出 匹配的文档,还要计算每个匹配文档的相关性,计算相关性使得它们比不评分查询费力的多。同时,查询结果并不缓存。
多亏倒排索引(inverted index),一个简单的评分查询在匹配少量文档时可能与一个涵盖百万文档的filter表现的一样好,甚至会更好。但是在一般情况下,一个filter 会比一个评分的query性能更优异,并且每次都表现的很稳定。
过滤(filtering)的目标是减少那些需要通过评分查询(scoring queries)进行检查的文档。
然而,为了明确和简单,我们用 "filter" 这个词表示不评分、只过滤情况下的查询。查询过滤的选择:使用 查询(query)语句来进行 全文 搜索或者其它任何需要影响 相关性得分 的搜索。除此以外的情况都使用过滤(filters)。
match --analyzed字段全文,not-analyzed字段精确
multi-match --多字段查询
term --精确查询
terms--精确多字段查询
range--范围查询
exists--有值 IS_NULL
missing--无值 NOT IS_NULL
must
文档 必须 匹配这些条件才能被包含进来。must_not
文档 必须不 匹配这些条件才能被包含进来。should
如果满足这些语句中的任意语句,将增加_score
,否则,无任何影响。它们主要用于修正每个文档的相关性得分。filter
必须 匹配,但它以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。通过将查询移到
filter
语句中,我们将它转成不评分的查询,将bool
查询包裹在filter
语句中,我们可以在过滤标准中增加布尔逻辑constant_score
查询。它将一个不变的常量评分应用于所有匹配的文档。它被经常用于你只需要执行一个 filter 而没有其它查询(例如,评分查询)的情况下。可以使用它来取代只有 filter 语句的
bool
查询。在性能上是完全相同的,但对于提高查询简洁性和清晰度有很大帮助。使用explain关键字来执行验证查询,分析查询中的错误
对于数字或日期,你可以将多值字段减为单值,这可以通过使用
min
、max
、avg
或是sum
排序模式 。例如你可以按照每个date
字段中的最早日期进行排序,通过以下方法:"sort": { "dates": { "order": "asc", "mode": "min" } }
以全文analyzed
字段排序会消耗大量的内存。所以可以添加not-analyzed子字段,使用该字段来排序。Elasticsearch 的相似度算法 被定义为检索词频率/反向文档频率, TF/IDF ,包括以下内容:
- 检索词频率
- 检索词在该字段出现的频率?出现频率越高,相关性也越高。 字段中出现过 5 次要比只出现过 1 次的相关性高。
- 反向文档频率
- 每个检索词在索引中出现的频率?频率越高,相关性越低。检索词出现在多数文档中会比出现在少数文档中的权重更低。
- 字段长度准则
- 字段的长度是多少?长度越长,相关性越低。 检索词出现在一个短的 title 要比同样的词出现在一个长的 content 字段权重更大
-
在
Elasticsearch
中,Doc Values
就是一种列式存储结构,默认情况下每个字段的Doc Values
都是激活的,Doc Values
是在索引时创建的,当字段索引时,Elasticsearch
为了能够快速检索,会把字段的值加入倒排索引中,同时它也会存储该字段的 `Doc Values`。Elasticsearch
中的Doc Values
常被应用到以下场景:- 对一个字段进行排序
- 对一个字段进行聚合
- 某些过滤,比如地理位置过滤
- 某些与字段相关的脚本计算
因为文档值被序列化到磁盘,我们可以依靠操作系统的帮助来快速访问。当
working set
远小于节点的可用内存,系统会自动将所有的文档值保存在内存中,使得其读写十分高速; 当其远大于可用内存,操作系统会自动把Doc Values
加载到系统的页缓存中,从而避免了jvm
堆内存溢出异常。
以上是关于Elasticsearch 搜索的主要内容,如果未能解决你的问题,请参考以下文章
Elasticsearch:如何在 Elasticsearch 中正确使用同义词功能
Elasticsearch:如何在 Elasticsearch 中正确使用同义词功能