映射操作

索引创建后,需要设置字段的约束信息,叫做字段映射(mapping)。字段的约束包括:字段的数据类型、是否要存储、是否要索引、分词器。

创建映射字段

语法:

PUT /索引名/_mapping
{
  "properties": {
    "字段名": {
      "type": "数据类型",
      "index": true,
      "store": false,
      "analyzer": "分词器"
    }
  }
}

示例:

PUT /wzkicu-index
PUT /wzkicu-index/_mapping/
{
  "properties": {
    "name": {
      "type": "text",
      "analyzer": "ik_max_word"
    },
    "job": {
      "type": "text",
      "analyzer": "ik_max_word"
    },
    "logo": {
      "type": "keyword",
      "index": "false"
    },
    "payment": {
      "type": "float"
    }
  }
}

映射属性详解

  • type 类型

    • String类型:text 可分词,不可参与聚合。keyword 不可分词,作为完整字段进行分配,可以参与聚合
    • Numerical类型:数值类型,分两类,基本数据类型、浮点数的高精度类型
    • Date:日期类型,ES 可以对日期格式化字符串存储,但是建议存储为毫秒值、存储为 long,节省空间
    • Array 数组类型:进行匹配时,任意一个元素满足,都认为满足
    • Object 对象:{ name: "jack", age: 21, girl: {name: "Rose", age: 21}},如果存储到索引库是对象类型,会把 girl 变成 girl.name 和 girl.age
  • index:true 字段会被索引,则可以用来进行搜索,默认值就是 true。false 字段不会被索引,不能用来搜索

  • store:是否将数据进行独立存储,原始的文本存储在 _source 里面,默认情况下其他提取出来的字段都不是独立存储的,是从 _source 里面提取出来的

  • analyzer:指定分词器,一般使用 IK 分词器 ik_max_word / ik_smart

查看映射关系

GET /索引名称/_mapping
GET _mapping
GET _all/_mapping

修改映射关系

主要注意的是:修改映射只能是增加字段的操作,其他的更改只能删除索引重新建立索引来实现。

一次性建立索引与映射

PUT /索引库名称
{
  "settings":{
    "索引库属性名":"索引库属性值"
  },
  "mappings":{
    "properties":{
      "字段名":{
        "映射属性名":"映射属性值"
      }
    }
  }
}

文档增删改查与局部更新

文档,即索引库中的数据,会根据规则创建索引,将用来搜索,可以类比做数据库中的一行数据。

新增文档

手动新增:

POST /索引名称/_doc/{id}
{
  "name" : "百度",
  "job" : "小度用户运营经理",
  "payment" : "30000",
  "logo" : "https://profile-avatar.csdnimg.cn/xxx.jpg"
}

自动新增:

POST /索引名称/_doc
{
  "field": "value"
}

查询文档

单个文档:

GET /索引名称/_doc/{id}

所有文档:

POST /索引名称/_search
{
  "query":{
    "match_all": {}
  }
}

定制返回字段:

GET /索引名称/_doc/1?_source=name,job

更新文档

全部更新:

PUT /索引名称/_doc/{id}
{
  "name" : "百度",
  "job" : "百度测试",
  "payment" : "20000",
  "logo" : "https://xxx.jpg"
}

局部更新:

POST /索引名/_update/{id}
{
  "doc":{
    "field":"value"
  }
}

注意:ES 执行更新操作的时候,ES 是先将旧的标记为删除,再添加新的文档。

删除文档

ID删除:

DELETE /索引名/_doc/{id}

条件删除:

POST /索引名/_delete_by_query
{
  "query": {
    "match": {
      "字段名": "搜索关键字"
    }
  }
}

删除所有:

POST /索引名/_delete_by_query
{
  "query": {
    "match_all": {}
  }
}

错误速查

症状根因定位修复
PUT 索引/_mapping 报错:mapper_parsing_exception已存在字段类型与本次提交的 type / analyzer 不兼容查看索引当前 _mapping,比对字段类型与新配置
修改已有字段类型后,旧数据查询行为”怪异”映射没真正变(老 segment 仍按旧映射)坚持”映射设计好再建索引”,需要调整时走”新索引 + reindex”方案
查询命中数为 0,但确认数据在 _source 中存在字段 index:false 或被映射为 keyword,而查询使用了分词匹配需要全文检索就用 text + analyzer;只做精确匹配用 keyword
keyword 字段做模糊搜索 / 中文搜索效果极差keyword 不分词,只存整值;中文必须配合分词器使用 text 类型常用模式:text + keyword 多字段
POST 索引/_update/id 报版本冲突误把”局部更新”和”全量覆盖”混用;或高并发下版本冲突局部更新统一用 _update + doc;高并发场景考虑乐观锁或重试策略
使用 DELETE_BY_QUERY 删除后,磁盘空间短期内几乎没变化ES 先”标记删除”,等待 segment merge 才真正回收空间属于正常行为,等待后台合并;空间压力大时考虑 force merge
查询 _source 返回字段过大,接口延迟与网络开销明显默认返回完整 _source,包含所有字段使用 ?_source=字段1,字段2 限制返回字段
全量更新 PUT 后发现”新增了一条数据”之前该 id 不存在,ES 将其视为新文档创建确认业务语义:需要”仅当存在才更新”时,需先 GET 或使用脚本更新条件