Elasticsearch基本操作
索引操作
创建索引
PUT /user
查询指定索引
GET /user
查询所有索引信息
GET _cat/indices?v
删除索引
DELETE /user
类型映射
动态映射
在关系型数据库中,得先创建表,指定字段和字段类型,才能将数据插入表中。
而elasticsearch
默认情况下不需要先创建索引,指定mapping
,就可以插入数据。会自动推断数据类型
PUT /user/_doc/1
{
"userId": 1,
"name": "zhang san",
"age": 20,
"birthday": "2022-08-20"
}
对于以上语句,如果索引user不存在,会先创建索引user,且自动推断字段类型,然后新增一条id=1的数据。
如果索引已经存在,多出来的字段,则会自动增加到mapping
中。
查询下索引mapping
信息
GET /user/_mapping
{
"user" : {
"mappings" : {
"properties" : {
"age" : {
"type" : "long"
},
"birthday" : {
"type" : "date"
},
"name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"userId" : {
"type" : "long"
}
}
}
}
}
会看到elasticsearch
自动推断出数据字段类型
字段 | 类型 |
---|---|
id | long |
name | text/keyword |
age | long |
birthday | date |
再次新增一条docId=2的数据
PUT /user/_doc/2
{
"userId": 2,
"name": "zhang san",
"age": 20,
"birthday": "2022-08-20",
"createTime": "2023-08-20 12:00:00"
}
此时索引已经存在,但是多了createTime
这个字段,会把createTime
增加到mapping
中。
再次查询索引mapping
,可以看到createTime字段。
GET /user/_mapping
{
"user" : {
"mappings" : {
"properties" : {
"age" : {
"type" : "long"
},
"birthday" : {
"type" : "date"
},
"createTime" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"userId" : {
"type" : "long"
}
}
}
}
}
指定映射
使用如下语句便可以在创建索引时指定字段以及类型
PUT /user
{
"mappings": {
"properties": {
"userId": {
"type": "integer",
"index": true
},
"name": {
"type": "text",
"index": true
},
"age": {
"type": "integer",
"index": true
},
"birthday": {
"type": "date",
"index": true
}
}
}
}
其中: "index": true
表示该列可以作为查询条件,可以省略,默认为true
查询映射
GET /user/_mapping
查询指定字段映射
GET /user/_mapping/field/userId
增加字段映射
PUT /user/_mapping
{
"properties": {
"createTime": {
"type": "date",
"index": false,
"format": "yyyy-MM-dd HH:mm:ss"
}
}
}
增加了一个创建时间
改变字段映射类型
比如想把createTime
改成long
类型,目前不支持此种操作,因为可能会使得已有数据无效
dynamic参数设置
- true,默认值,即动态映射,自动推断字段和类型,创建mapping
- false,非动态模式,无法根据输入文档的内容,自动创建mapping,需要手动创建mapping
- strict,严格模式,同非动态模式,区别在于,非动态模式,输入的文档中如果有字段不在mapping中,依然可以存储和读取,但是该字段不在mapping中,因此也无法根据该字段进行检索;但严格模式,无法存储,会直接报错,严格模式实际上就类似于关系型数据库中的表了。
语法如下所示:
创建索引同时指定mapping
PUT /user/
{
"mappings": {
"dynamic": "strict",
"properties": {
"userId": {
"type": "long"
}
}
}
}
文档基本操作
新增或者修改文档
PUT | POST /索引名称/_doc/docId
其中PUT必须指定id,POST若不指定,则会自动生成随机ID,在带id参数路径是,PUT和POST语义一样。
在指定id时,若id不存在则新增,否则修改(修改的是所有字段,若请求体没有包含某个字段,则该字段不会再保存,将查询不到)。
POST方法不带id时,因为会自动生成随机id,所以每次都是新增。
指定id方式(PUT或者POST)
PUT /user/_doc/1
{
"userId": 1,
"name": "zhang san",
"age": 20,
"birthday": "2022-08-20",
"createTime": "2022-08-20 12:10:30"
}
随机ID(POST),当然了POST方式也可以指定ID
POST /user/_doc
{
"userId": 1,
"name": "zhang san",
"age": 20,
"birthday": "2022-08-20",
"createTime": "2022-08-20 12:10:30"
}
进行修改,故意少写createTime
PUT /user/_doc/1
{
"userId": 1,
"name": "zhang san",
"age": 25,
"birthday": "1997-08-20"
}
查询结果(createTime会丢失)
{
"userId": 1,
"name": "zhang san",
"age": 25,
"birthday": "1997-08-20"
}
新增文档
使用_create方式,如果id存在,会报错。
PUT /user/_create/1
{
"userId": 1,
"name": "zhang san",
"age": 20,
"birthday": "2022-08-20",
"createTime": "2022-08-20 12:10:30"
}
修改文档
使用_update方式,可以修改指定的字段,若id不存在,会报错
仅仅修改age字段
POST /user/_update/1
{
"doc": {
"age": 25
}
}
或者
POST /user/_doc/1/_update
{
"doc": {
"age": 25
}
}
查看文档
GET /user/_doc/1
删除文档
DELETE /user/_doc/1
批量操作
使用_bulk
API
包含四种操作,可以同时存在
- index,存在则修改,否则新增
- create,新增
- update,修改
- delete,删除
下面对user索引批量新增文档,注意,除了delete不需要紧跟数据,其它操作都需要接一条数据,无论是操作还是数据,都是一行完成。
POST /user/_bulk
{"index": {"_id": 1}}
{"userId": 1, "name" : "zhang san", "age" : 20, "birthday" : "2021-08-20", "createTime" : "2022-08-20 12:10:30"}
{"index": {"_id": 2}}
{"userId": 2, "name" : "li si", "age" : 20, "birthday" : "2022-08-20", "createTime" : "2022-08-20 12:10:30"}
{"index": {"_id": 3}}
{"userId": 3, "name" : "zhang san shuo", "age" : 25, "birthday" : "2022-08-20", "createTime" : "2022-08-20 12:10:30"}
{"index": {"_id": 4}}
{"userId": 4, "name" : "wang wu", "age" : 20, "birthday" : "2021-08-20", "createTime" : "2022-08-20 12:10:30"}
文档搜索
查找所有
GET /user/_search
或者
GET /user/_search
{
"query": {
"match_all": {}
}
}
简单查询
注意,对于类型为text
的列,会进行分词
假设现在有以下数据
[
{
"userId" : 1,
"name" : "zhang san",
"age" : 20,
"birthday" : "2022-08-20",
"createTime" : "2022-08-20 12:10:30"
},
{
"userId" : 2,
"name" : "li si",
"age" : 20,
"birthday" : "2022-08-20",
"createTime" : "2022-08-20 12:10:30"
}
]
现在根据名称查询
GET /user/_search
{
"query": {
"match": {
"name": "zhang"
}
}
}
会找到zhang san
那条记录
GET /user/_search
{
"query": {
"match": {
"name": "zhang li"
}
}
}
会找到zhang san
和li si
两条记录,因为搜索条件会被分词为zhang
和li
两个词
如果想要搜索条件作为整体出现,可以使用match_phrase
如以下例子
GET /user/_search
{
"query": {
"match_phrase": {
"name": "zhang li"
}
}
}
该命令将不会查到任何结果,因为没有任何记录的名字包含zhang li
继续增加一条数据,假设目前的结果如下
[
{
"userId" : 1,
"name" : "zhang san",
"age" : 20,
"birthday" : "2022-08-20",
"createTime" : "2022-08-20 12:10:30"
},
{
"userId" : 2,
"name" : "li si",
"age" : 20,
"birthday" : "2022-08-20",
"createTime" : "2022-08-20 12:10:30"
},
{
"userId" : 3,
"name" : "zhang san shuo",
"age" : 25,
"birthday" : "2022-08-20",
"createTime" : "2022-08-20 12:10:30"
}
]
执行以下查询
GET /user/_search
{
"query": {
"match_phrase": {
"name": "zhang san"
}
}
}
将会得到zhang san
以及zhang san shuo
两条记录,因为这两条记录的名字都包含zhang san
。
match_phrase
匹配逻辑:首先也会将搜索条件进行分词,并且每个词都要命中记录,且分词的相对位置也要一样。比如搜索zhang shuo
是不会匹配到zhang san shuo
这条记录的,因为顺序不一致,中间还有一个san
,虽然分词zhang
和shuo
都能命中。
范围查询
GET /user/_search
{
"query": {
"range": {
"age": {
"gte": 10,
"lte": 20
}
}
}
}
复杂查询
must = and,should = or
查找名字包含zhang san
,年龄为25的记录
GET /user/_search
{
"query": {
"bool": {
"must": [
{
"match_phrase": {
"name": "zhang san"
}
},
{
"match": {
"age": 25
}
}
]
}
}
}
得到结果为name=zhang san shuo
,age=25的记录
查找名字包含zhang san
或者年龄为25的记录
GET /user/_search
{
"query": {
"bool": {
"should": [
{
"match_phrase": {
"name": "zhang san"
}
},
{
"match": {
"age": 25
}
}
]
}
}
}
得到结果为name=zhang san shuo
,age=25的记录以及name=zhang san
,age=20的记录
查找(name like '%zhang san%' or age = 25) and birthday = '2022-08-20'
GET /user/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"birthday": "2022-08-20"
}
},
{
"bool": {
"should": [
{
"match_phrase": {
"name": "zhang san"
}
},
{
"match": {
"age": 25
}
}
]
}
}
]
}
}
}
查找指定列
GET /user/_search
{
"query": {
"match_all": {}
},
"_source": ["name", "age"]
}
排序
GET /user/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"age": {
"order": "desc"
},
"userId": {
"order": "asc"
}
}
]
}
分页
GET /user/_search
{
"track_total_hits": true,
"query": {
"match_all": {}
},
"sort": [
{
"age": {
"order": "desc"
},
"userId": {
"order": "asc"
}
}
],
"from": 0,
"size": 2
}
注:
from: 默认为0
size: 默认为10
from + size 的和不能超过10000,这个值由参数max_result_window决定,默认为10000。
"track_total_hits": true,表示返回精确的总数量,否则超过10000条数据时,总数总是返回10000。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构