之前我们了解了动态的Mapping设置,我们知道ES提供了mapping的字段类型的一个推算,会根据你第一次写入文档的字段的值去推算设置mapping的字段类型。但是我们又说这个推算是不准确的,可能和你的预想出现偏差,之前我们也验证过了。
因为不准确,所以我们在实际开发的时候一般不会完全去依赖他的推算,更多的是我们按照业务要求,显式的指定字段的类型,所以这次我们就来处理手动指定类型mapping的操作。

一、如何显式定义一个Mapping

1、简介

显式定义的语法很简单,但是我们先明确一点,我们定义的是Index索引的mapping,所以这个mapping是我们第一次添加index索引的时候指定的。
其简单语法为:

PUT indexName
{
	"mappings":{
		// 在这里定义你的mapping结构
	}
}

2、实际操作的方法

2.1、参考官网

可以参考官网纯手写,这个没说的,多写写就熟练了。

2.2、建立临时索引,再修改

我们可以利用前面说的动态mapping,先设置进去一个,让ES帮我们推断,然后我们查出这个mapping结构,在上面做一些修改,把他推断错的改过来就行,然后删掉那个临时的。再使用修改好的,创建出你要的最终版就行了。

3、控制当前字段是否被索引

有时候我们创建一个索引,建立mapping的时候,有些字段我们不希望可以被用户检索到。这样我们可以在显示创建mapping的时候。在某些字段上指定是否可以被索引。
如果你设置成false,则该字段不可以被搜索。如果你不设置,默认就是true。
比如下面:

PUT users   创建一个users索引,显式的设置其mapping
{
  "mappings": {
    "properties": {
      "firstName":{
        "type": "text"
      },
      "lastName":{
        "type": "text"
      },
      "mobile":{
        "type": "text",
        "index": false  指定这个字段不可以被索引,也就是无法被搜索,他的倒排索引就不会被创建
      }
    }
  }
}

举个例子:
1、先建立一个索引并且指定其中字段为index:false

#设置 index 为 false
DELETE users
PUT users
{
    "mappings" : {
      "properties" : {
        "firstName" : {
          "type" : "text"
        },
        "lastName" : {
          "type" : "text"
        },
        "mobile" : {
          "type" : "text",
          "index": false   把电话设置为不可索引
        }
      }
    }
}

2、在这个索引中插入一个文档

PUT users/_doc/1
{
  "firstName":"Ruan",
  "lastName": "Yiming",
  "mobile": "12345678"
}

3、尝试检索一下mobile这个字段

POST /users/_search
{
  "query": {
    "match": {
      "mobile":"12345678"
    }
  }
}

查询报错,

"caused_by": {
            "type": "illegal_argument_exception",
            "reason": "Cannot search on field [mobile] since it is not indexed." 不能被索引的字段mobile
          }

所以验证了我们上面的理论。

4、Index Options

查看es的资源 查看es的mapping_开发语言


这里简单说明一下,docs级别只记录doc id就是在创建倒排索引的时候,倒排记录只有docId,别的没有,类似mysql中的二级索引存的不是全记录一样。

5、null_value

有的时候我们在文档中希望存入一些null值,而且我们也希望这些null值也被索引到,这时候我们就可以指定null_value属性。
同时也要知道,只有keyword类型才支持null_value。具体语法如下。

PUT users
{
  "mappings": {
    "properties": {
      "firstName":{
        "type": "text"
      },
      "lastName":{
        "type": "text"
      },
      "mobile":{
        "type": "text",
        "index": false
      },
      "sex":{
        "type": "keyword",
        "null_value": "NULL" 以后你插入文档的时候sex就能存为Null,而且还支持查询
      }
    }
  }
}

支持查询,GET users/_search?q=sex:NULL这样也能搜出来对应的文档。
举个例子看下:

#设定Null_value

DELETE users
PUT users
{
    "mappings" : {
      "properties" : {
        "firstName" : {
          "type" : "text"
        },
        "lastName" : {
          "type" : "text"
        },
        "mobile" : {
          "type" : "keyword",
          "null_value": "NULL"
        }

      }
    }
}

PUT users/_doc/1
{
  "firstName":"Ruan",
  "lastName": "Yiming",
  "mobile": null
}


PUT users/_doc/2
{
  "firstName":"Ruan2",
  "lastName": "Yiming2"

}

GET users/_search   可以搜到第一个数据,第二个搜不到,因为他搜的是真的null,你写的那个Null
{
  "query": {
    "match": {
      "mobile":"NULL"
    }
  }
}

6、copy_to 设置

查看es的资源 查看es的mapping_java_02


不常使用,用到了再说吧。

测试一下:

1、创建一个索引指定mapping

PUT users
{
  "mappings": {
    "properties": {
      "firstName":{
        "type": "text",
        "copy_to": "fullName"
      },
      "lastName":{
        "type": "text",
        "copy_to": "fullName"
      }
    }
  }
}
我们指定了firstName 和 lastName,并且copy_to到了fullName这里面去,注意这个fullName不是真的存在的。

2、插入一个文档

PUT users/_doc/1
{
  "firstName":"Ruan",
  "lastName": "Yiming"
}

3、我们去检索一下
注意此时我们检索的是fullName条件。

GET users/_search?q=fullName:(Ruan Yiming)

POST users/_search
{
  "query": {
    "match": {
       "fullName":{
        "query": "Ruan Yiming",
        "operator": "and"
      }
    }
  }
}
我们用的fullName查询是能查到的,但是_source里面没这个字段。
 "_source" : {
      "firstName" : "Ruan",
       "lastName" : "Yiming"
 }
 我们只是把这个firstName和lastName映射到了fullName里面,这个属性是不存在的。
 具体可以理解为Mysql中的虚拟列。

二、ES的数据类型

1、数组类型

ES中是不支持专门的数组类型的,但是对于任何字段,都可以包含多个相同类型的数值,起到和数组一样的效果。类似效果如下。

PUT users/_doc/1
{
  "name":"test1",
  "hobby":"redis"
}

PUT users/_doc/2
{
  "name":"test2",
  "hobby":["redis,mysql"]  存入了一个类似数组结构的数据
}

具体例子如下:

#数组类型
PUT users/_doc/1
{
  "name":"onebird",
  "interests":"reading"
}

PUT users/_doc/1
{
  "name":"twobirds",
  "interests":["reading","music"]
}

POST users/_search
{
  "query": {
		"match_all": {}
	}
}

GET users/_mapping

三、总结

ES其实常用的还是显式的mapping,具体的一些语法在使用的时候注意随机应变。