Elasticsearch中的mapping和分析过程

映射mapping

自定义表结构 (原本是es自动帮我们定义的)

每个索引都有一个映射类型(6.x版本前可有多个)

参考博客: https://www.cnblogs.com/Neeo/articles/10585039.html

字段的数据类型:

1.简单类型:
*文本(text)	*关键字(keyword)	日期(data)	整形(long)	双精度(double)	   布尔(boolean)	ip

2.支持JSON的层次结构性质的类型:
对象		嵌套

3.特殊类型:
geo_point		geo_shape	  completion(纠正和建议)

mapping的操作实例

PUT a2
{
  "mappings": {
    "doc":{
      "properties":{
        "name":{
          "type":"text"
        },
        "age":{
          "type":"long"
        }
      }
    }
  }
}

GET a2/_mapping

POST a2/doc/1		#创建数据也可以用POST
{
  "name":"黄飞鸿",
  "age":19
}

GET a2/doc/1

dynamic三种状态

dynamic true 动态映射

PUT a2
{
  "mappings": {
    "doc":{
      "dynamic":true,		#关键所在
      "properties":{
        "name":{
          "type":"text"
        },
        "age":{
          "type":"long"
        }
      }
    }
  }
}

POST a2/doc/1		#正常按照字段增加数据
{
  "name":"黄飞鸿",
  "age":19
}

POST a2/doc/2		#多加了一个定义时没有的city字段
{
  "name":"李晓龙",
  "age":19,
  "city":"广州"
}

POST a2/doc/3		#忽略定义时定义的name字段
{
  "age":19,
  "city":"广州"
}

GET a2/doc/_search		#查找没有问题!
{
  "query": {
    "match": {
      "city": "广州"
    }
  }
}

不限制新增或忽略某个字段,并且新增的字段也可以作为查询的主条件

dynamic false 静态映射 (常用)

"dynamic":true,
不限制新增或忽略某个字段,但在查找的时候不给新增的字段做分词,也就是说新增的字段不会主动添加新的映射关系,只能作为查询结果出现在查询中!所以新增的字段不能作为主查询条件

dynamic strict 严格模式

"dynamic":"strict",
不允许新增字段,但可以忽略字段

mapping的其他设置

index属性

# index属性
PUT a5
{
  "mappings": {
    "doc":{
      "dynamic":"strict",
      "properties":{
        "name":{
          "type":"text"
        },
        "age":{
          "type":"long",
          "index":true
        },
        "city":{
          "type":"text",
          "index":false
        }
      }
    }
  }
}


POST a5/doc/1
{
  "name":"李尔新",
  "age":19,
  "city":"长春"
}

POST a5/doc/2
{
  "name":"周子谦",
  "age":19,
  "city":"长春"
}

GET a5/doc/_search
{
  "query": {
    "match": {
      "city": "长春"
    }
  }
}

# 字段的index属性值为false的话不会为该字段创建索引,也就是无法当做查询的主条件!

copy_to属性

PUT a6
{
  "mappings": {
    "doc":{
      "properties":{
        "name":{
          "type":"text",
          "copy_to":"full_name"		#将这个字段的内容copy到full_name字段里
        },
        "age":{
          "type":"long",
          "copy_to":"full_name"
        },
        "full_name":{		#full_name字段
          "type":"text"
        }
      }
    }
  }
}

POST a6/doc/1
{
  "name":"周子谦",
  "age":19
}

GET a6/doc/_search
{
  "query": {
    "match": {
      "name": "周子谦"
    }
  }
}

GET a6/doc/_search
{
  "query": {
    "match": {
      "full_name": 19		#full_name能查名字也能查年龄
    }
  }
}
PUT a7
{
  "mappings": {
    "doc":{
      "properties":{
        "name":{
          "type":"text",
          "copy_to":["f1","f2"]		#可以copy到多个字段
        },
        "age":{
          "type":"long"
        },
        "f1":{
          "type":"text"
        },
        "f2":{
          "type":"text"
        }
      }
    }
  }
}

POST a7/doc/1
{
  "name":"周子谦",
  "age":19
}

GET a7/doc/_search
{
  "query": {
    "match": {
      "f1": "周子谦"		#f1 f2都可代替name作为主查询条件
    }
  }
}

对象属性 properties

# 对象属性
PUT a8
{
  "mappings": {
    "doc":{
      "properties":{
        "name":{
          "type":"text"
        },
        "age":{
          "type":"long"
        },
        "info":{
          "properties":{
            "addr":{
              "type":"text"
            },
            "tel":{
              "type":"text"
            }
          }
        }
      }
    }
  }
}

PUT a8/doc/1
{
  "name":"王涛",
  "age":33,
  "info":{
    "addr":"长春",
    "tel":"10018"
  }
}

GET a8/doc/_search
{
  "query": {
    "match": {
      "info.addr": "长存"
    }
  }
}

# 奇技淫巧:正常顺序是PUT mapping后再POST插入数据,最后才能GET查询的,我们也可以直接POST,然后GET a8/_mapping查看es帮我们自动生成的mapping,然后复制过来修改即可

ignore_above属性

PUT w1
{
  "mappings": {
    "doc":{
      "properties":{
        "t1":{
          "type":"keyword",
          "ignore_above": 5		#设置ignore_above属性
        },
        "t2":{
          "type":"keyword",
          "ignore_above": 10	#设置ignore_above属性
        }
      }
    }
  }
}
PUT w1/doc/1
{
  "t1":"elk",
  "t2":"elasticsearch"
}
GET w1/doc/_search
{
  "query":{
    "term": {
      "t1": "elk"	#查t1有结果
    }
  }
}

GET w1/doc/_search
{
  "query": {
    "term": {
      "t2": "elasticsearch"   #查t2无结果,超过设定的最大长度了
    }
  }
}

# 设定最大长度,超过长度的字符不会创建索引!

设置settings

PUT a9
{
  "settings": {
    "number_of_shards": 1,		#一个索引对应的主分片数量
    "number_of_replicas": 0		#一块主分片对应的副分片数量
  }
}

分析过程

当数据发送到es后, 在加入倒排索引之前, es对该文档进行的一系列操作

  • 字符过滤 : 使用字符过滤器转变字符 (特殊字符, 如 & --> and)
  • 文本切分为分词 : 将文本(档)分为多个单词或多个分词
  • 分词过滤 : 使用分词过滤器转变每个分词
  • 分词索引 : 最终将分词存储在Lucene倒排索引中
  • 参考博客: https://www.cnblogs.com/Neeo/articles/10401392.html

分析器

标准分析器

POST _analyze
{
  "analyzer": "standard",
  "text":"To be or not to be,  That is a question ———— 莎士比亚"
}

简单分析器 ( 对亚种语言效果不佳 )

POST _analyze
{
  "analyzer": "simple",
  "text":"To be or not to be,  That is a question ———— 莎士比亚"
}

空白分析器

# 只根据空白切分...
POST _analyze
{
  "analyzer": "whitespace",
  "text":"To be or not to be,  That is a question ———— 莎士比亚"
}

停用词分析器

POST _analyze
{
  "analyzer": "stop",
  "text":"To be or not to be,  That is a question ———— 莎士比亚"
}

停用词:
1.功能词 is the on...
2.词汇词 want...

关键词分析器

#将整个字段作为单独的分词,一般不用...
POST _analyze
{
  "analyzer": "keyword",
  "text":"To be or not to be,  That is a question ———— 莎士比亚"
}

模式分析器

#允许我们指定一个分词切分模式,但是通常更佳的方案是使用定制的分析器,组合现有的模式分词器和所需要的分词过滤器更加合适。
POST _analyze
{
  "analyzer": "pattern",
  "explain": false, 
  "text":"To be or not to be,  That is a question ———— 莎士比亚"
}
# 我们来自定制一个模式分析器,比如我们写匹配邮箱的正则。
# 需要注意的是,在json字符串中,正则的斜杠需要转义!
PUT pattern_test
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_email_analyzer":{
          "type":"pattern",
          "pattern":"\\W|_",
          "lowercase":true
        }
      }
    }
  }
}

语言和多语言分析器

#一般也不用...
POST _analyze
{
  "analyzer": "chinese",
  "text":"To be or not to be,  That is a question ———— 莎士比亚"
}

雪球分析器

#除了使用标准的分词和分词过滤器(和标准分析器一样)也是用了小写分词过滤器和停用词过滤器,除此之外,它还是用了雪球词干器对文本进行词干提取。
POST _analyze
{
  "analyzer": "snowball",
  "text":"To be or not to be,  That is a question ———— 莎士比亚"
}

字符过滤器 char_filter

分词器 tokenizer

分词过滤器 token filter

ik 分词器

  GET _analyze
{
  "analyzer": "ik_smart",
  "text": "上海自来水来自海上"
}

#更细
GET _analyze
{
  "analyzer": "ik_max_word",
  "text": "上海自来水来自海上"
}
PUT ik1
{
  "mappings": {
    "doc": {
      "dynamic": false,
      "properties": {
        "content": {
          "type": "text",
          "analyzer": "ik_max_word"   #ik分词器
        }
      }
    }
  }
}
#增加数据
PUT ik1/doc/1
{
  "content":"今天是个好日子"
}
PUT ik1/doc/2
{
  "content":"心想的事儿都能成"
}
PUT ik1/doc/3
{
  "content":"我今天不活了"
}
#查找中文分词 没问题
GET ik1/doc/_search
{
  "query": {
    "match": {
      "content": "今天"
    }
  }
}
上一篇:Django之MySQL配置部署


下一篇:Kibana Dev Tools应用