基于 Elasticsearch 2.x 版本,有些内容可能已经过时。
基本概念
索引(名词):类似于传统关系数据库中的一个数据库。
索引(动词):索引一个文档就是存储一个文档到一个索引(名词),类似于SQL语句中的INSERT,除了文档已存在时,新文档会替换旧文档情况之外。
倒排索引:关系型数据库通过增加一个索引比如B树索引到指定的列上以便提升数据检索速度。Elasticsearch和Lucene使用了
一个叫做倒排索引的结构来达到相同的目的。默认的,一个文档中的每一个属性都是被索引的(有一个倒排索引),没有倒排索引
的属性不能被搜索到。
文档元数据
_index
_type
_id
索引名规范:小写,不能以下划线开头,不能包含逗号。
类型命名规范:大写或小写,不能以下划线或句号开头,不能包含逗号,长度限制为256个字符
2
查询
http://172.20.15.200:9801/
_search POST
{"query":{"match":{"FPHM":"91110010"}}}
POST /megacorp/employee/_search
{
"query" : {
"match" : {
"NSRSBH" : "20191106"
}
}
}
0
计算集群中文档的数量
GET http://localhost:9200/_count?pretty
{
"query":{
"match_all":{}
}
}
1
增加一个文档
PUT /megacorp/employee/1 注:其中megacorp是索引,employee是类型,1是员工的ID
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
如果使用自己的id,使es在相同_index,_type和_id不存在时才接受索引请求。
方式一PUT /megacorp/employee/1?op_type=create
{...}
方式二PUT /megacorp/employee/1/_create
{...}
如果创建新文档的请求成功执行,Elasticsearch 会返回元数据和一个 201 Created 的 HTTP 响应码。
另一方面,如果具有相同的 _index 、 _type 和 _id 的文档已经存在,Elasticsearch 将会返回 409 Conflict 响应码,以及如下的错误信息
如果不指定文档ID则用POST
删除文档
DELETE /website/blog/123
删除类型下的全部数据
POST http://172.20.15.200:9801/dzdz_fpxx_dzfp201311/dzdz_fpxx_dzfp/_delete_by_query/
处理同时对文档修改的冲突问题
悲观并发控制
这种方法被关系型数据库广泛使用,它假定有变更冲突可能发生,因此阻塞访问资源以防止冲突。 一个典型的例子是读取一行数据之前先将其锁住,确保只有放置锁的线程能够对这行数据进行修改。
乐观并发控制
Elasticsearch 中使用的这种方法假定冲突是不可能发生的,并且不会阻塞正在尝试的操作。 然而,如果源数据在读写当中被修改,更新将会失败。应用程序接下来将决定该如何解决冲突。 例如,可以重试更新、使用新的数据、或者将相关情况报告给用户。
方法一(更新和删除文档,都可以接受version参数)
es通过_version号确保新旧版本的执行顺序
通过指定想要修改文档的version号确保应用中相互冲突的变更不会丢失。
创建文档
PUT /website/blog/1/_create
{...}
获取该文档版本号
GET /website/blog/1
通过指定版本号修改该文档
PUT /website/blog/1?version=1
方法二 通过外部系统使用版本控制(更新和删除文档)
此方法es不是检查当前_version和请求中指定的版本号是否相同,而是检查当前_version
是否小于指定的版本号。如果请求成功,外部的版本号作为文档的新_version进行存储
PUT /website/blog/2?version=5&version_type=external
{...}
文档的部分更新
POST /website/blog/1/_update
{
"doc" : {
"tags" : [ "testing" ],
"views": 0
}
}
或,注:使用脚本需要设置集群所有节点的config/elasticsearch.yml文件来启动动态Groovy脚本:
script.groovy.sandbox.enable:true
POST /website/blog/1/_update
{
"script" : "ctx._source.views+=1"
}
2
检索文档
GET /megacorp/employee/1
查询索引下数据 get
http://172.20.15.200:9801/dzdz_da_jsxx/
注:PUT 改为 GET 可以用来检索文档,同样的,可以使用 DELETE 命令来删除文档,以及使用 HEAD 指令来检查文档是否存在。如果想更新已存在的文档,只需再次 PUT 。
查询类型下的所有数据
GET /megacorp/employee/_search
查询类型下姓氏为Smith的员工
GET /megacorp/employee/_search?q=last_name:Smith 注:其中last_name为文档的属性,Smith为文档的属性值
注:Query-string 搜索通过命令非常方便地进行临时性的即席搜索 ,但它有自身的局限性
查询表达式搜索
GET /megacorp/employee/_search
{
"query" : {
"match" : {
"last_name" : "Smith"
}
}
}
查询姓氏为Smith,年龄大于30的员工
GET /megacorp/employee/_search
{
"query" : {
"bool": {
"must": {
"match" : {
"last_name" : "smith"
}
},
"filter": {
"range" : {
"age" : { "gt" : 30 }
}
}
}
}
}
POST /dzdz_da_nsrxx/_search
{
"query" : {
"bool": {
"must": {
"match" : {
"SWJGMC" : "湖南省长沙市岳麓区税务局"
}
},
"filter": {
"range" : {
"id" : { "gt" : 30 }
}
}
}
}
}
相关性匹配。Elasticsearch默认按照相关性得分排序,即每个文档跟查询的匹配程度。
如果想要精确匹配可使用match_phrase。会搜索到属性中包含搜索关键字的文档
高亮搜索:在搜索结果中高亮部分文本片段,以便让用户知道为何该文档符合查询条件
GET /megacorp/employee/_search
{
"query" : {
"match_phrase" : {
"SWJGMC" : "湖南省长沙市岳麓区税务局"
}
},
"highlight": {
"fields" : {
"SWJGMC" : {}
}
}
}
返回文档的一部分
GET /website/blog/123?_source=title,text 注:_source只返回请求的字段
GET /website/blog/123/_source 注:只想得到_source部分,不包含任何元数据
检查文档是否存在
可以用HEAD方法代替GET方法,HEAD请求没有返回体,只返回一个HTTP请求报头:
curl -i -XHEAD http://localhost:9200/website/blog/123
如果文档存在, Elasticsearch 将返回一个 200 ok 的状态码
若文档不存在, Elasticsearch 将返回一个 404 Not Found 的状态码
取回多个文档。将多个请求合并成一个,避免单独处理每个请求花费的网络延时和开销
GET /_mget
{
"docs" : [
{
"_index" : "website",
"_type" : "blog",
"_id" : 2
},
{
"_index" : "website",
"_type" : "pageviews",
"_id" : 1,
"_source": "views"
}
]
}
该响应体也包含一个 docs 数组, 对于每一个在请求中指定的文档,这个数组中都包含有一个对应的响应,且顺序与请求中的顺序相同。 其中的每一个响应都和使用单个 get request 请求所得到的响应体相同:
即使有某个文档没有找到,上述请求的 HTTP 状态码仍然是 200 。事实上,即使请求 没有 找到任何文档,它的状态码依然是 200 --因为 mget 请求本身已经成功执行。 为了确定某个文档查找是成功或者失败,你需要检查 found 标记。
批量操作
POST /_bulk
{ action: { metadata }}\n
{ request body }\n
{ action: { metadata }}\n
{ request body }\n
...
例如:
POST /_bulk
{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title": "My first blog post" }
{ "index": { "_index": "website", "_type": "blog" }}
{ "title": "My second blog post" }
{ "update": { "_index": "website", "_type": "blog", "_id": "123", "_retry_on_conflict" : 3} }
{ "doc" : {"title" : "My updated blog post"} }
注:
1请注意 delete 动作不能有请求体,它后面跟着的是另外一个操作。
2谨记最后一个换行符不要落下。
3 bulk 请求不是原子的: 不能用它来实现事务控制。每个请求是单独处理的,因此一个请求的成功或失败不会影响其他的请求。
空搜索
没有指定任何查询的空搜索,它简单地返回集群中所有索引下的所有文档
GET /_search
/_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 类型
分页
如果每页展示 5 条结果,可以用下面方式请求得到 1 到 3 页的结果:
GET /_search?size=5
GET /_search?size=5&from=5
GET /_search?size=5&from=10
size
显示应该返回的结果数量,默认是 10
from
显示应该跳过的初始结果数量,默认是 0
轻量搜索:在查询字符串中传递所有参数。
1查询在 tweet 类型中 tweet 字段包含 elasticsearch 单词的所有文档:
GET /_all/tweet/_search?q=tweet:elasticsearch
2查询在 name 字段中包含 john 并且在 tweet 字段中包含 mary 的文档
+name:john +tweet:mary
注:+ 前缀表示必须与查询条件匹配。类似地, - 前缀表示一定不与查询条件匹配。没有 + 或者 - 的所有其他条件都是可选的——匹配的越多,文档就越相关。
3_all字段
搜索返回包含 mary 的所有文档
GET /_search?q=mary
Elasticsearch 是如何在三个不同的字段中查找到结果的呢?
当索引一个文档的时候,Elasticsearch 取出所有字段的值拼接成一个大的字符串,作为 _all 字段进行索引。例如,当索引这个文档时:
{
"tweet": "However did I manage before Elasticsearch?",
"date": "2014-09-14",
"name": "Mary Jones",
"user_id": 1
}
这就好似增加了一个名叫 _all 的额外字段:
"However did I manage before Elasticsearch? 2014-09-14 Mary Jones 1"
下面的查询针对tweents类型,并使用以下的条件:
name 字段中包含 mary 或者 john
date 值大于 2014-09-10
_all 字段包含 aggregations 或者 geo
+name:(mary john) +date:>2014-09-10 +(aggregations geo)
排序
GET /_search?sort=date:desc&sort=_score&q=search
轻量搜索的缺点:
1一些查询字符串中很小的语法错误,像 - , : , / 或者 " 不匹配等,将会返回错误而不是搜索结果
2查询字符串搜索允许任何用户在索引的任意字段上执行可能较慢且重量级的查询,这可能会暴露隐私信息,甚至将集群拖垮
索引方式不同造成搜索结果不一样:
例如:
在我们的索引中有12条推文,其中只有一条包含日期 2014-09-15 ,但是看一看下面查询命中的 总数 (total):
GET /_search?q=2014 # 12 results
GET /_search?q=2014-09-15 # 12 results !
GET /_search?q=date:2014-09-15 # 1 result
GET /_search?q=date:2014 # 0 results !
_all字段查询和date字段查询返回的结果不同,原因是date字段和string字段索引方式不同
倒排索引
当查询一个全文域时(如_all),只能搜索在索引中出现的词条,否则查不到,索引索引文本和查字符串必须标准化为相同的格式
当查询一个精确值域时(如date域),是啥就是啥。
映射
索引中每个文档都有类型,每种类型都有它自己的映射,或者模式定义。映射定义了类型中的域,
每个域的数据类型,以及es如何处理这些域。映射也用于配置与类型有关的元数据。
1核心简单域类型
字符串:string
整数:byte,short,integer,long
浮点数:
布尔型:boolean
日期:date
索引发包新域(属性)的文档,es会根据json中基本数据类型来自动映射
JSON type -》 域 type
布尔型: true 或者 false -》boolean
整数: 123 -》long
浮点数: 123.45 -》double
字符串,有效日期: 2014-09-15 -》date
字符串: foo bar -》string
查看映射
/_mapping,可查看es在一个或多个索引中的一个或多个类型的映射
例如
GET /gb/_mapping/tweet
自定义域映射
自定义域映射可以实现:
全文字符串域和精确值字符串域的区别
使用特定语言分析器
优化域以适应部分匹配
指定自定义数据格式
。。。
string域映射的属性
(1)index属性
控制怎样索引字符串:analyzed-分析字符串,然后索引它,即以全文索引这个域。
not_analyzed-索引这个域,所以它能够被搜索,但索引的是精确值。不会对它进行分析
no-不索引这个域,这个域不会被搜索到。
注:string域index属性默认是analyzed。如果想映射这个字段为一个精确值,我们
需要设置它为not_analyzed
(2)analyzer属性
对于analyzed字符串,用analyzer属性指定在搜索和索引时的分析器。默认es使用standard分析器
更新映射
当首次创建一个索引时,可以指定类型的映射:
例如:创建gb索引,指定tweet类型的映射
PUT /gb
{
"mappings": {
"tweet" : {
"properties" : {
"tweet" : {
"type" : "string",
"analyzer": "english"
},
"date" : {
"type" : "date"
},
"name" : {
"type" : "string"
},
"user_id" : {
"type" : "long"
}
}
}
}
}
在tweet映射增加一个新的名为tag的not_analyzed的文本域:
PUT /gb/_mapping/tweet
{
"properties" : {
"tag" : {
"type" : "string",
"index": "not_analyzed"
}
}
}
如上,我们可以创建索引时指定类型的映射,也可以给一个映射新增一个新域,但不能将一个
存在的域从analyzed改为not_analyzed
复杂核心域类型
除了简单标量数据类型,JSON还有null值,数组和对象。
(1)数组
{ "tag": [ "search", "nosql" ]}
注:任何域都可以包含多个值,但是数组中的值必须是相同的数据类型。es的数组是无序的。
(2)空域
以下三种域被认为是空的,他们将不会被索引:
"null_value": null,
"empty_array": [],
"array_with_null_value": [ null ]
(3)多层级对象
{
"tweet": "Elasticsearch is very flexible",
"user": {
"id": "@johnsmith",
"gender": "male",
"age": 26,
"name": {
"full": "John Smith",
"first": "John",
"last": "Smith"
}
}
}
内部对象的映射
{
"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" }
}
}
}
}
}
}
}
}
请求体查询
空查询
(1) 查询所有索引库的所有文档
GET /_search
{}
(2)查询一个、多个或_all索引库和一个、多个或者所有types中查询:
GET /index_2014*/type1,type2/_search
{}
(3)同时可以使用from和size参数来分页:
GET /_search
{
"from": 30,
"size": 10
}
注:因为带请求体GET请求不被广泛支持,所以search API同时支持POST请求。
(4)
空查询(empty search) —{}— 在功能上等价于使用 match_all 查询, 正如其名字一样,匹配所有文档:
GET /_search
{
"query": {
"match_all": {}
}
}
查询语句的结构
(1)
GET /_search
{
"query": YOUR_QUERY_HERE
}
(2)
{
QUERY_NAME: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}
(3)针对某个字段
{
QUERY_NAME: {
FIELD_NAME: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}
}
(4)合并查询语句
几个重要的查询
(1)match_all匹配所有文档
{"match_all":{}}
(2)match如果你在一个全文字段上使用 match 查询,在执行查询前,它将用正确的分析器去分析查询字符串:
{"match":{"tweet":"About Search"}}
如果在一个精确值的字段上使用它,例如数字、日期、布尔或者一个 not_analyzed 字符串字段,那么它将会精确匹配给定的值:
{ "match": { "age": 26 }}
{ "match": { "date": "2014-09-01" }}
{ "match": { "public": true }}
{ "match": { "tag": "full_text" }}
(3)multi_match查询可以在多个字段执行相同的match查询
{
"multimatch":{
"query":"full text search",
"fields":["title","body"]
}
}
(4)range查询找出那些落在指定区间内的数字或时间
{
"range":{
"age":{
"gte":20,
"lt":30
}
}
}
注:gt gte lt lte
(5)term查询被用于精确值匹配,这些精确值可能是数字、时间、布尔或者那些 not_analyzed 的字符串:
被用于精确值匹配,这些精确值可能是数字、时间、布尔或者那些 not_analyzed 的字符串:
(6)terms查询
terms 查询和 term 查询一样,但它允许你指定多值进行匹配。如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件:
{ "terms": { "tag": [ "search", "full_text", "nosql" ] }}
(7)exists查询和missing查询
exists 查询和 missing 查询被用于查找那些指定字段中有值 (exists) 或无值 (missing) 的文档。这与SQL中的 IS_NULL (missing) 和 NOT IS_NULL (exists) 在本质上具有共性:
{
"exists": {
"field": "title"
}
}
组合多查询
可以使用bool查询来实现组合多查询,它的参数有:
must:文档匹配该条件才能查到
must_not:文档不匹配该条件
should:如果满足该条件,将增加_score,否则,无任何影响。主要用于修正每个文档的相关性得分
filter:必须匹配,但不评分
例:
下面的查询用于查找 title 字段匹配 how to make millions 并且不被标识为 spam 的文档。那些被标识为 starred 或在2014之后的文档,将比另外那些文档拥有更高的排名。如果 两者 都满足,那么它排名将更高:
{
"bool": {
"must": { "match": { "title": "how to make millions" }},
"must_not": { "match": { "tag": "spam" }},
"should": [
{ "match": { "tag": "starred" }},
{ "range": { "date": { "gte": "2014-01-01" }}}
]
}
}
注:
如果没有 must 语句,那么至少需要能够匹配其中的一条 should 语句。但,如果存在至少一条 must 语句,则对 should 语句的匹配没有要求。
bool 查询本身也可以被用做不评分的查询。简单地将它放置到 filter 语句中并在内部构建布尔逻辑:
bool 查询本身也可以被用做不评分的查询。简单地将它放置到 filter 语句中并在内部构建布尔逻辑:
{
"bool": {
"must": { "match": { "title": "how to make millions" }},
"must_not": { "match": { "tag": "spam" }},
"should": [
{ "match": { "tag": "starred" }}
],
"filter": {
"bool": {
"must": [
{ "range": { "date": { "gte": "2014-01-01" }}},
{ "range": { "price": { "lte": 29.99 }}}
],
"must_not": [
{ "term": { "category": "ebooks" }}
]
}
}
}
}
constant_score查询
它被经常用于你只需要执行一个 filter 而没有其它查询(例如,评分查询)的情况下。
可以使用它来取代只有 filter 语句的 bool 查询。在性能上是完全相同的,但对于提高查询简洁性和清晰度有很大帮助。
{
"constant_score": {
"filter": {
"term": { "category": "ebooks" }
}
}
}
验证查询
用validate-query API验证查询是否合法
例如:
GET /gb/tweet/_validate/query?explain
{
"query": {
"tweet" : {
"match" : "really powerful"
}
}
}
对于合法查询,使用 explain 参数将返回可读的描述,这对准确理解 Elasticsearch 是如何解析你的 query 是非常有用的:
每一个 index 都会返回对应的 explanation ,因为每一个 index 都有自己的映射和分析器:
排序
1
GET /_search
{
"query" : {
"bool" : {
"filter" : { "term" : { "user_id" : 1 }}
}
},
"sort": { "date": { "order": "desc" }}
}
2指定一个字段用来排序
"sort": "number_of_children"
字段将会默认升序排序,而按照 _score 的值进行降序排序。
多级排序
按照date和_score排序
GET /_search
{
"query" : {
"bool" : {
"must": { "match": { "tweet": "manage text search" }},
"filter" : { "term" : { "user_id" : 2 }}
}
},
"sort": [
{ "date": { "order": "desc" }},
{ "_score": { "order": "desc" }}
]
}
多值字段的排序
按照每个 date 字段中的最早日期进行排序,通过以下方法:
"sort": {
"dates": {
"order": "asc",
"mode": "min"
}
}
字符串排序与多字段
以全文analyzed字段排序会消耗大量内存,排序要以not_analyzed字符串。但我们仍
需要analyzed字段,才能以全文进行查询。
因此,我们传递一个单字段并用两种方式索引它。这通过fields参数实现。
"tweet": {
"type": "string",
"analyzer": "english"
}
用两种方式索引
"tweet": {
"type": "string",
"analyzer": "english",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
}
注:1tweet主字段是一个analyzed全文字段
2tweet.raw子字段是not_analyzed
现在可以使用tweet字段用于搜索,tweet.raw字段用于排序
GET /_search
{
"query": {
"match": {
"tweet": "elasticsearch"
}
},
"sort": "tweet.raw"
分析器
测试分析器
GET /_analyze
{
"analyzer": "standard",
"text": "Text to analyze"
}
查看字符串分析结果
GET /my_store/_analyze
{
"field": "productID",
"text": "XHDK-A-1293-#fJ3"
}
结构化搜索
结构化数据:指日期、时间、数字有精确格式的文本
结构化查询不关心文件的相关度或评分,它简单地对文档包括或排除处理。
注意:用term进行精确值查找时,查找的字段如果是字符串要将其设置成not_analyzed的。
如果该字符串已经被设置成其他类型,要先删除其所在索引,再重建了。
DELETE /my_store
PUT /my_store
{
"mappings" : {
"products" : {
"properties" : {
"productID" : {
"type" : "string",
"index" : "not_analyzed"
}
}
}
}
}
注:删除索引是必须的,因为我们不能更新已存在的映射。
组合过滤器
1布尔过滤器
{
"bool" : {
"must" : [],
"should" : [],
"must_not" : [],
}
}
must
所有的语句都 必须(must) 匹配,与 AND 等价。
must_not
所有的语句都 不能(must not) 匹配,与 NOT 等价。
should
至少有一个语句要匹配,与 OR 等价
例1
SELECT product
FROM products
WHERE (price = 20 OR productID = "XHDK-A-1293-#fJ3")
AND (price != 30)
{
"query":{
"filtered":{
"filter":{
"bool":{
"should":[
{"term":{"price":20}},
{"term":{"productID":"XHDK-A-1293-#fJ3"}}
],
"must_not":{
"term":{"price":30}
}
}
}
}
}
}
注意: 仍然需要一个 filtered 查询将所有的东西包起来。
嵌套布尔过滤器
注:布尔过滤器是一个复合的过滤器,可以接受多个子过滤器,需要注意的是bool过滤器
本身仍然只是一个过滤器,可以将一个布尔过滤器置于其他bool过滤器内部。
SELECT document
FROM products
WHERE productID = "KDKE-B-9947-#kL5"
OR ( productID = "JODL-X-1937-#pV7"
AND price = 30 )
GET /my_store/products/_search
{
"query" : {
"filtered" : {
"filter" : {
"bool" : {
"should" : [
{ "term" : {"productID" : "KDKE-B-9947-#kL5"}},
{ "bool" : {
"must" : [
{ "term" : {"productID" : "JODL-X-1937-#pV7"}},
{ "term" : {"price" : 30}}
]
}}
]
}
}
}
}
}
terms 查询价格字段值是20或30的文档
{
"terms":{
"price":[20,30]
}
}
与term查询一样,也需要将其置于filter语句的常量评分查询中:
{
"query":{
"constant_score":{
"filter":{
"terms":{
"price":[20,30]
}
}
}
}
}
包含,而不是相等
注意:term和terms是包含操作,而非等值。
如果我们有一个 term(词项)过滤器 { "term" : { "tags" : "search" } } ,它会与以下两个文档 同时 匹配:
{ "tags" : ["search"] }
{ "tags" : ["search", "open_source"] }
精确相等
如果一定期望得到我们前面说的那种行为(即整个字段完全相等),最好的方式是增加并索引另一个字段, 这个字段用以存储该字段包含词项的数量,同样以上面提到的两个文档为例,现在我们包括了一个维护标签数的新字段:
{ "tags" : ["search"], "tag_count" : 1 }
{ "tags" : ["search", "open_source"], "tag_count" : 2 }
一旦增加这个用来索引项 term 数目信息的字段,我们就可以构造一个 constant_score 查询,来确保结果中的文档所包含的词项数量与要求是一致的:
GET /my_index/my_type/_search
{
"query": {
"constant_score" : {
"filter" : {
"bool" : {
"must" : [
{ "term" : { "tags" : "search" } },
{ "term" : { "tag_count" : 1 } }
]
}
}
}
}
}
范围
SELECT document
FROM products
WHERE price BETWEEN 20 AND 40
GET /my_store/products/_search
{
"query" : {
"constant_score" : {
"filter" : {
"range" : {
"price" : {
"gte" : 20,
"lt" : 40
}
}
}
}
}
}
range查询同意可以应用在日期字段上:
"range" : {
"timestamp" : {
"gt" : "2014-01-01 00:00:00",
"lt" : "2014-01-07 00:00:00"
}
}
range支持对日期计算操作,比如,查找时间戳在过去一小时内的所有文档
"range" : {
"timestamp" : {
"gt" : "now-1h"
}
}
日期计算还可以被应用到某个具体的时间,并非只能是一个像 now 这样的占位符。只要在某个日期后加上一个双管符号 (||) 并紧跟一个日期数学表达式就能做到:
"range" : {
"timestamp" : {
"gt" : "2014-01-01 00:00:00",
"lt" : "2014-01-01 00:00:00||+1M"
}
}
注:早于 2014 年 1 月 1 日加 1 月(2014 年 2 月 1 日 零时)
range查询同样可以处理字符串字段,字符串范围可采用字典顺序或字母顺序
处理空值??
exists和missing
匹配查询
match是高级全文查询,它既能处理全文字段,又能处理精确字段。
默认分析器
1分析器可以从三个层面进行定义:按字段(per-field)、按索引(per-index)或全局缺省(global default)。Elasticsearch 会按照以下顺序依次处理,直到它找到能够使用的分析器。索引时的顺序如下:
字段映射里定义的 analyzer ,否则
索引设置中名为 default 的分析器,默认为
standard 标准分析器
2在搜索时,顺序有些许不同:
查询自己定义的 analyzer ,否则
字段映射里定义的 analyzer ,否则
索引设置中名为 default 的分析器,默认为
standard 标准分析器
3Elasticsearch 也支持一个可选的 search_analyzer 映射,它仅会应用于搜索时( analyzer 还用于索引时)。还有一个等价的 default_search 映射,用以指定索引层的默认配置。
如果考虑到这些额外参数,一个搜索时的 完整 顺序会是下面这样:
查询自己定义的 analyzer ,否则
字段映射里定义的 search_analyzer ,否则
字段映射里定义的 analyzer ,否则
索引设置中名为 default_search 的分析器,默认为
索引设置中名为 default 的分析器,默认为
standard 标准分析器
4分析器配置实践
可以在索引级别设置中,为绝大部分的字段设置你想指定的 default 默认分析器。然后在字段级别设置中,对某一两个字段配置需要指定的分析器
注:
对于和时间相关的日志数据,通常的做法是每天自行创建索引,由于这种方式不是从头创建的索引,仍然可以用 索引模板(Index Template) 为新建的索引指定配置和映射。???
聚合
文档
PUT /megacorp/employee/1
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
统计员工的爱好,统计每个爱好的文档数量
GET /megacorp/employee/_search
{
"aggs": {
"all_interests": {
"terms": { "field": "interests" }
}
}
}
聚合支持分级汇总,比如:查询特定兴趣爱好员工的平均年龄
GET /megacorp/employee/_search
{
"aggs" : {
"all_interests" : {
"terms" : { "field" : "interests" },
"aggs" : {
"avg_age" : {
"avg" : { "field" : "age" }
}
}
}
}
}