1、如何建立索引

  • analyzed: full text 会建立倒排索引
  • not_analyzed:不会建立倒排索引,走的是 exact value 搜索
  • no:不走索引

2、修改 mapping

只能创建index时手动建立mapping,或者新增field mapping,但是不能update field mapping
创建 index 时,手动创建索引:

  1. PUT /website
  2. {
  3. "mappings": {
  4. "_doc": {
  5. "properties": {
  6. "author_id": {
  7. "type": "long"
  8. },
  9. "title": {
  10. "type": "text",
  11. "analyzer": "english"
  12. },
  13. "content": {
  14. "type": "text"
  15. },
  16. "post_date": {
  17. "type": "date"
  18. },
  19. "publisher_id": {
  20. "type": "text",
  21. "index": "not_analyzed"
  22. }
  23. }
  24. }
  25. }
  26. }

报错:

{
  "error" : {
    "root_cause" : [
      {
        "type" : "illegal_argument_exception",
        "reason" : "The mapping definition cannot be nested under a type [_doc] unless include_type_name is set to true."
      }
    ],
    "type" : "illegal_argument_exception",
    "reason" : "The mapping definition cannot be nested under a type [_doc] unless include_type_name is set to true."
  },
  "status" : 400
}

出现这个的原因是,elasticsearch7默认不在支持指定索引类型,默认索引类型是_doc,如果想改变,则配置include_type_name: true 即可(这个没有测试,官方文档说的,无论是否可行,建议不要这么做,因为elasticsearch8后就不在提供该字段)。
改为如下:

PUT /newwebsite
{
  "mappings": {
      "properties":{
        "author_id": {
          "type": "long"
        },
        "content": {
          "type": "text",
          "analyzer": "english"
        },
        "title": {
          "type": "text"
        },
        "post_date": {
          "type": "date"
        },
        "publisher_id": {
          "type": "text",
          "index": "not_analyzed"
        }
      }
  }
}

报错:

{
  "error" : {
    "root_cause" : [
      {
        "type" : "mapper_parsing_exception",
        "reason" : "Failed to parse mapping [_doc]: Could not convert [publisher_id.index] to boolean"
      }
    ],
    "type" : "mapper_parsing_exception",
    "reason" : "Failed to parse mapping [_doc]: Could not convert [publisher_id.index] to boolean",
    "caused_by" : {
      "type" : "illegal_argument_exception",
      "reason" : "Could not convert [publisher_id.index] to boolean",
      "caused_by" : {
        "type" : "illegal_argument_exception",
        "reason" : "Failed to parse value [not_analyzed] as only [true] or [false] are allowed."
      }
    }
  },
  "status" : 400
}

index这个只能用true或者false了,如果想要不被分词就把数据类型设置为keyword
解决如下:

PUT /newwebsite
{
  "mappings": {
      "properties":{
        "author_id": {
          "type": "long"
        },
        "content": {
          "type": "text",
          "analyzer": "english"
        },
        "title": {
          "type": "text"
        },
        "post_date": {
          "type": "date"
        },
        "publisher_id": {
          "type": "keyword"
        }
      }
  }
}
{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "newwebsite"
}

更新字段的数据类型:

PUT /newwebsite
{
  "mappings": {
      "properties": {
        "author_id": {
          "type": "text"
        }
      }
  }
}

结果报错:

{
  "error" : {
    "root_cause" : [
      {
        "type" : "resource_already_exists_exception",
        "reason" : "index [newwebsite/Ym0xShwxQ1iChJuxNrjqRA] already exists",
        "index_uuid" : "Ym0xShwxQ1iChJuxNrjqRA",
        "index" : "newwebsite"
      }
    ],
    "type" : "resource_already_exists_exception",
    "reason" : "index [newwebsite/Ym0xShwxQ1iChJuxNrjqRA] already exists",
    "index_uuid" : "Ym0xShwxQ1iChJuxNrjqRA",
    "index" : "newwebsite"
  },
  "status" : 400
}

向 index 添加需要创建 mapping 的 field :

PUT /newwebsite/_mapping
{
  "properties" : {
    "new_field" : {
      "type" :    "string",
      "index":    false
    }
  }
}

报错如下:

{
  "error" : {
    "root_cause" : [
      {
        "type" : "mapper_parsing_exception",
        "reason" : "No handler for type [String] declared on field [new_field]"
      }
    ],
    "type" : "mapper_parsing_exception",
    "reason" : "No handler for type [String] declared on field [new_field]"
  },
  "status" : 400
}
报错原因

我使用的Elasticsearch是6.2.2版本,按照学习文档创建字段时,使用了{"type":"string","index":"not_analyzed"}

原因分析

检查拼写无误之后,我决定去查Elasticsearch新版本特性,因为之前也踩过head插件的安装方法的坑,就是因为版本问题。
果不其然,Elasticsearch从5.X就引入了text和keyword,其中keyword适用于不分词字段,搜索时只能完全匹配,这时string还保留着。
到了6.X就彻底移除string了。
另外,”index”的值只能是boolean变量了。

解决方法
{"type":"text","index":false}

案例:

PUT /newwebsite/_mapping
{
  "properties" : {
    "new_field" : {
      "type": "text",
      "index": false
    }
  }
}

3、测试mapping

查看 content 字段的分词结果:

GET /newwebsite/_analyze
{
  "field": "content",
  "text": "my-dogs" 
}

查看 new_field 字段的分词结果:

GET /newwebsite/_analyze
{
  "field": "new_field",
  "text": "my dogs"
}

由于 new_fieldindex 配置为 not_analyzed 所以不走可以分词:

{
  "error": {
    "root_cause": [
      {
        "type": "remote_transport_exception",
        "reason": "[4onsTYV][127.0.0.1:9300][indices:admin/analyze[s]]"
      }
    ],
    "type": "illegal_argument_exception",
    "reason": "Can't process field [new_field], Analysis requests are only supported on tokenized fields"
  },
  "status": 400
}

ES7.x 中没有 not_analyzed