查询
使用 from 和 size 分页查询,需要注意的是:from+size
要小于 10000,不然会报错
// 从第9条开始,查询100条
GET index_test/_search?from=9&size=100
// 这个也行
GET index_test/_search
{
"from":9,
"size":100
}
查询某个 id: DE7BEo0BngUdM_im08lv
GET index_test/_doc/DE7BEo0BngUdM_im08lv
查询结果不要元字段,只查询 _source
,使用 _source
api 加上 id
GET index_test/_source/2
一次性查询多个 id 值
GET index_test/_mget
{
"ids":[1,2]
}
GET index_test/_search
{
"query":{
"ids": {
"values":[1,2,4]
}
}
}
match
match 搜索需要注意以下几点:
- 被查询字段必须是可以分词的,比如 name 字段必须是可以分词的,例如 text 类型。
- 搜索过程是:首先对搜索词进行分词,然后只要一个某个分词和被搜索字段的分词匹配上了,就满足。、
- es 分词的时候,首先会对分词统一改成小写,所以不区分大小写了。
例如下例子中,name 字段必须是可以分词的字段,然后搜索词 小米手机
,会被分词
GET index_test/_search
{
"query":{
"match": {
"name": "小米手机"
}
}
}
搜索词分词的时候,本身也会作为分词结果之一,例如 HuaWei Mate 9000
会作为一个特殊项,作为整体去匹配
GET index_test/_search
{
"query":{
"match": {
"name.keyword": "HuaWei Mate 9000"
}
}
}
match_phrase
这个查询和 match 查询一样,不同点在于所有分词要按顺序都匹配上
- 会对搜索词进行分词
- 搜索词的分词必须全部匹配上,并且顺序也要相同,中间不能有其他词。
- 中间不能有其它词,不过这个可以通过 slop 配置允许多少个其他词,默认是 0 个。
例如下例中:搜索词 xiao mi
会被分词成 xiao
、mi
两个单词。这两个单词去 name 的分词中搜索,如果 name 中有个 xiao mi
既可以被匹配上,如果 name 是 xiao x mi
就不能匹配上,因为中间有其他干扰词语。
GET index_test/_search
{
"query":{
"match_phrase": {
"name": "xiao mi"
}
}
}
可以通过 slop 参数配置干扰词的数量,例如下例中,slop=1,这样 name 是 xiao x mi
就能匹配上了
GET index_test/_search
{
"query":{
"match_phrase": {
"name": {
"query": "小米手机",
"slop": 1
}
}
}
}
term
一般用于精确查询
- 不会对搜索词进行分词,会保留搜索词的所有属性,包括大小写,标点符号等。
- 被搜索字段一般是子字段 keyword(text 类型一般都有子字段,叫做 keyword,记录着原始信息,不过文本内容如果太长的话,就会忽略,导致搜索不到),或者其他不分词的字段
- 被搜索是可以分词的字段也是可以,需要和分词结果匹配上就行
下面例子中,Xiao mi shou ji
会作为整体去匹配,name 必须也是 Xiao mi shou ji
才可以被匹配上
GET index_test/_search
{
"query":{
"term": {
"name.keyword": {
"value": "Xiao mi shou ji"
}
}
}
}
如果想要一次搜索多个词,可以用 terms
GET index_test/_search
{
"query":{
"terms": {
"name.keyword": ["xiao mi shou ji","hua wei shou ji"]
}
}
}
range
只支持大于,大于等于,小于,小于等于
GET index_test/_search
{
"query":{
"range": {
"age":{
"gte":10,
"lte":20
}
}
}
}
bool 组合
组合查询,就是多条件查询,bool 里的每个条件自己是 and 关系。
must
must 查询,定义多个必须同时满足的条件
GET index_test/_search
{
"_source":fase, // 关掉
"query":{
"bool": {
"must": [
// 多个条件必须同时满足
{
"match": {
"FIELD": "TEXT"
},
"match_phrase": {
"FIELD": "PHRASE"
}
}
]
}
}
}
filter
filter 和 must 是一样的,只是会缓存,没有计算评分排序,如果不需要排序,用这个会快一点
GET index_test/_search
{
"query":{
"bool": {
"filter": [
{
"match": {
"name": "小米"
},
"range": {
"price": {
"lte": 20
}
}
}
]
}
}
}
should
should 子句,和 or 有点类型,但是不等价
GET index_test/_search
{
"query":{
"bool": {
"should": [
{
"match": {
"name": "小米"
},
"range": {
"price": {
"lte": 20
}
}
}
],
"minimum_should_match": 1 // should 条件应该满足的个数,默认就是1
}
}
}
must not
must not,子条件都不能满足,但凡满足一个都不行
GET index_test/_search
{
"query":{
"bool": {
"must_not": [
{
"match": {
"name": "小米"
},
"range": {
"price": {
"lte": 20
}
}
}
]
}
}
}
嵌套子查询
嵌套子查询,需要再加上 bool。
下例中:name != iphone AND ((name = phone AND price <= 20) OR (type = phone AND brand IN ("苹果","华为")))
{
"query": {
"bool": {
"must_not": [
{
"match": {
"name": "iphone"
}
}
],
"should": [
{
"bool": {
"must": [
{
"match": {
"name": "phone"
}
},
{
"range": {
"price": {
"lte": 20
}
}
}
]
}
},
{
"bool": {
"must": [
{
"match": {
"type": "phone"
}
},
{
"terms": {
"brand.keywords": [
"华为",
"苹果"
]
}
}
]
}
}
]
}
}
}
索引操作
因为,新增文档的时候,如果索引不存在也会自动创建,没有必要特意创建,了解就行
创建索引 index_test
,请求体 body 可以没有。
PUT index_test
{
"settings":{
"number_of_shards":1,// 主分片数量
"number_of_replicas":1 // 每个主分片的副本分片数量
}
}
修改索引 index_test
PUT index_test/_settings
{
"number_of_shards":1
}
删除索引,这个操作要小心
DELETE index_test
新增文档
创建数据,1
是文档 id,如果已经存在就会报错
PUT index_test/_doc/1?op_type=create
{
"name":"手机",
"content":"小米"
}
等效 _create
api
PUT index_test/_create/2
{
"name":"手机",
"content":"小米"
}
如果 id 已经存在,希望更新的话,可以使用 index,这个更新是覆盖掉原来的内容
PUT index_test/_doc/1?op_type=index
{
"name":"手机1",
"content":"小米"
}
// 不加op_type=index 也一样
PUT index_test/_doc/1
{
"name":"手机1",
"content":"小米"
}
创建文档的时候,不指定 id,系统自动生成 uuid
POST index_test/_doc/
{
"name":"手机1",
"content":"小米"
}
批量创建,使用 bulk 接口,批量创建,注意不能格式化,必须一行是命令,下一行是数据,中间不能有换行和空格。
POST /_bulk
{"create":{"_index":"index_test","_id":5}} // 命令
{"name":"手机5","content":"123"} // 数据
{"create":{"_index":"index_test","_id":6}}
{"name":"手机6","content":"123"}
{"create":{"_index":"index_test","_id":7}}
{"name":"手机7","content":"123"}
// 已经存在的不报错
POST /_bulk
{"index":{"_index":"index_test","_id":5}}
{"name":"手机5","content":"123"}
{"index":{"_index":"index_test","_id":6}}
{"name":"手机6","content":"123"}
{"index":{"_index":"index_test","_id":7}}
{"name":"手机7","content":"123"}
删除文档
删除的时候,要加上文档 id
DELETE index_test/_doc/DE7BEo0BngUdM_im08lv
批量删除
POST /_bulk
{"delete":{"_index":"index_test","_id":5}}
{"delete":{"_index":"index_test","_id":6}}
通过条件删除
POST /index_test/_delete_by_query
{
"query":{
"term": {
"price": 500
}
}
}
更新文档
更新 name 字段,这个时候要加上 doc 属性,如果有多个字段,就把相应的字段新增上去就很
POST index_test/_update/1
{
"doc":{
"name":"手机1"
}
}
批量更新
POST /_bulk
{"update":{"_index":"index_test","_id":5}}
{"doc":{"name":"手机55"}}
{"update":{"_index":"index_test","_id":6}}
{"doc":{"name":"手机66"}}
mapping 操作
mapping 相当于 mysql 的表结构,定义索引的了 es 的数据结构等信息
GET index_test/_mapping
es 的字段可以有多个类型,如果是文本类型,系统默认会创建一个 keword 类型,字段名称就叫做 keword
- text 类型,字段内容会被分词,不会区服大小写
- keword 类型,不会被分词,用于精确查询,会区分大小写,字段太长的时候会被忽略会搜索不到
- nested 类型,字段是个 json 对象,或者是个数组里嵌套对象,这种比较复杂的类型
{
"index_test": {
"mappings": {
"properties": {
"content": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"price": {
"type": "long"
}
}
}
}
}
不像 mysql 使用表之前,需要先定义好表结构,es 添加数据的时候,可以新增字段,会自动传教 mapping,es 会更加值类型,创建相应的字段类型
PUT index_test/_create/10
{
"name":"手机",
"content":"小米2",
"price":500 // 例如此时没有price字段
}
虽然 mapping 可以自动创建,不过最好手动创建,只能创建索引的时候设置好,后面很多参数都不允许修改
PUT index_test1
{
"mappings":{
"properties":{
"long_field":{
"type":"long"
}
}
}
}
测试分词
查看分词结果
GET index_test/_analyze
{
"text":["华为mate"]
}