Elasticsearch 7.x 深入【1】索引【二】创建

1. 借鉴

极客时间 阮一鸣老师的Elasticsearch核心技术与实战
官方文档 creating_an_index
官方文档 mapping
官方文档 multi-fields

2. 开始

创建索引

在前面,我们知道了什么是es中的索引,接下来我们就来创建一个索引

方式1:通过索引一篇文档创建一个新索引

  • 比如:一开始并没有酒店的索引,我想创建一个有关酒店的索引
PUT /hotel/_doc/1
{
  "name": "测试酒店1",
  "grade": 2.5,
  "address": "北京市"
}
  • 上面这个语句创建了id为1包含三个属性(name,grade,address)的酒店

突然我想加为这篇文档添加/删除/修改一个属性怎么办呢?好的,多问几个为什么,我们会在后续讲,我会把连接粘贴到这里 // TODO

  • 太草率了吧,这样就创建了索引了么。是的-_-,那如果我要将文档2添加到hotel索引中该如何呢?
PUT /hotel/_doc/2
{
  "name": "测试酒店2",
  "grade": 3,
  "address": "上海市"
}
  • 可以看到,当你索引第一篇新文档时会自动创建索引(es会自动根据数据格式识别它的类型),我们可以查看一下这篇索引的结构
  • 在kibana中键入以下语句,查看索引的结构

GET /hotel/_mapping

  • 可以看到kibana控制台返回以下信息
{
  "hotel" : {
    "mappings" : {
      "properties" : {
        "address" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "grade" : {
          "type" : "float"
        },
        "name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}
  • 额,那这些都是些什么呢,第二语言是英语的看官能猜出来个大概,我们标记一下


    属性解析
  • 可能有疑问的就是fields属性了,我在文章开头贴上了官方文档[multi-fields],这里再简单解释一下,什么叫”为不同的目的以不同的方式索引相同的字段“。最常用的同一个字段指定不同的分词器,比如说都是name字段,我使用两个分词器,一个是简体中文分词器,另外一个是拼音分词器,那么我们就可以使用fields定义两个分词器,一个是用于简体中文分词器,另外一个是拼音分词器,类似于下面这种,(如果运行下面这个语句报错,先下载ik和pinyin分词器 // TODO es插件下载),搜索的时候指定同一个字段的不同属性进行查询,比如我们有以下索引:
PUT /hotel_multi_fields
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "ik_smart",
        "fields": {
          "pinyin": {
            "type": "text",
            "analyzer": "pinyin"
          }
        }
      }
    }
  }
}
  • 那我们根据两个属性来进行查询
# 添加文档
# googledjd
PUT /hotel_multi_fields/_doc/1
{
  "name": "google大酒店"
}

PUT /hotel_multi_fields/_doc/2
{
  "name": "微软大酒店"
}

# 查询
# 使用name属性查询
GET /hotel_multi_fields/_search
{
  "query": {
    "term": {
      "name": {
        "value": "google"
      }
    }
  }
}

# 使用name.pinyin属性来查询
GET /hotel_multi_fields/_search
{
  "query": {
    "term": {
      "name.pinyin": {
        "value": "wrdjd"
      }
    }
  }
}

全字段的解析会在后面的章节有详解。额,好像走远了。。。

  • 当然这种方式有一定限制,但是读到这里的看官一般不会遇到,我会在后续章节详细叙述一些属性对于此种方式的限制。(// TODO)

方式2:通过指定mappings来创建一个新索引

  • 方式1是基于es的动态索引类型识别,但是这种动态识别,有时候识别的并不是我们想要的结果。那我们就来举个栗子:我要索引hotel,name为文本类型,gradle为double类型,adress为文本类型,distance为double类型;但是我在创建索引文档的时候不小心类型输入错误了,输入了字符串类型,我们基于以上做测试。
# 先删除已有索引
DELETE /hotel

# 创建hotel索引,并索引id为1的文档[这种就是方式1,一气呵成对吧]
PUT /hotel/_doc/1
{
  "name": "测试酒店1",
  "grade": 2.5,
  "address": "北京市",
  "distance": "25.0"
}

# 我们来看看它的索引结构
GET /hotel/_mapping
  • 返回结果如下
{
  "hotel" : {
    "mappings" : {
      "properties" : {
        "address" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "distance" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "grade" : {
          "type" : "float"
        },
        "name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}
  • 我们不小心设置错了类型它就将错就错,得到了我们不想要的结果,当然责任主要在我们。那接下来,我们精确的设置一下类型呢?
# 先删除已有索引
DELETE /hotel

# 指定索引结构
PUT /hotel
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text"
      },
      "grade": {
        "type": "double"
      },
      "address": {
        "type": "text"
      },
      "distance": {
        "type": "double"
      }
    }
  }
}

# 再次插入相同的数据
PUT /hotel/_doc/1
{
  "name": "测试酒店1",
  "grade": 2.5,
  "address": "北京市",
  "distance": "25.0"
}

# 看看它的索引结构
GET /hotel/_mapping
{
  "hotel" : {
    "mappings" : {
      "properties" : {
        "address" : {
          "type" : "text"
        },
        "distance" : {
          "type" : "double"
        },
        "grade" : {
          "type" : "double"
        },
        "name" : {
          "type" : "text"
        }
      }
    }
  }
}
# 看下数据
GET /hotel/_search
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "hotel",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "name" : "测试酒店1",
          "grade" : 2.5,
          "address" : "北京市",
          "distance" : "25.0"
        }
      }
    ]
  }
}
  • 可以看到,数据虽然是文本类型,但是索引本身并没有更改,如果我们这时新增一篇文档,把distance设置为非数字的文本呢?
PUT /hotel/_doc/2
{
  "name": "测试酒店1",
  "grade": 2.5,
  "address": "北京市",
  "distance": "啊哈哈"
}
  • 结果会报错
{
  "error": {
    "root_cause": [
      {
        "type": "mapper_parsing_exception",
        "reason": "failed to parse field [distance] of type [double] in document with id '2'. Preview of field's value: '啊哈哈'"
      }
    ],
    "type": "mapper_parsing_exception",
    "reason": "failed to parse field [distance] of type [double] in document with id '2'. Preview of field's value: '啊哈哈'",
    "caused_by": {
      "type": "number_format_exception",
      "reason": "For input string: \"啊哈哈\""
    }
  },
  "status": 400
}
  • 由此我们会猜测它内部会调用Double.valueOf()方法,如果报错就抛出来,如果是文本数字 的话,还能使用。

更多的时候,我们需要确定索引的结构,而非让es自动匹配,同时以便在我们设置错误的类型时es也能给我提示。

  • 所以创建用此方式创建索引的最简模板就是
PUT /索引的名字
{
  "mappings": {
    "properties": {
      "xxx1属性": {
        "type": "该属性的类型"
      },
     "xxx2属性": {
        "type": "该属性的类型"
      }
    }
  }
}

比如我们创建一个person的索引

PUT /person
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text"
      },
      "age": {
        "type": "integer"
      },
      "sex": {
        "type": "boolean"
      }
    }
  }
}

除了以上简单的属性,我们还可参看官方文档有关mapping的更多属性(连接参看借鉴部分 [官方文档 mapping])

3. 大功告成

你可能感兴趣的:(Elasticsearch 7.x 深入【1】索引【二】创建)