索引创建原则
- 类似的数据放在一个索引,非类似的数据放不同索引:product index(包含了所有的商品),sales index(包含了所有的商品销售数据),inventory index(包含了所有库存相关的数据)。比如product,sales,human resource(employee),如果全都放在一个大的index里面,比如说company index,是不合适的。
- index中包含了很多类似的document:类似是什么意思,其实指的就是这些document的fields很大一部分是相同的,比如说放了3个document,每个document的fields都完全不一样,这就不是类似了,就不太适合放到一个index里面去。
- 索引名称必须是小写的,不能用下划线开头,不能包含逗号:product,website,blog
_index:索引
_type:类型
创建索引
PUT /my_index
{
"settings": { ... any settings ... },
"mappings": {
"type_one": { ... any mappings ... },
"type_two": { ... any mappings ... },
...
}
}
初识mapping
- 自动或手动为index中的type建立的一种数据结构和相关配置,简称为mapping。
- dynamic mapping,自动为建立index,创建type,以及type对应的mapping,mapping中包含了每个field对应的数据类型,以及如何分词等设置。当然,也可以手动在创建数据之前,先创建index和type,以及type对应的mapping。
- es自动建立mapping的时候,设置不同的field、不同的data type、不同的data type的分词索等行为是不一样的。所以会出现_all field(搜索所有的field,任意一个field包含指定的关键字就可以搜索出来)和post_date field的搜索表现完全不一样。
对mapping的理解
(1)往es里面直接插入数据,es会自动建立索引,同时建立type以及对应的mapping;
(2)mapping中就自动定义了每个field的数据类型;
(3)不同的数据类型(比如说text和date),可能有的是exact value,有的是full text;
(4)exact value,在建立倒排索引的时候,分词的时候,是将整个值一起作为一个关键词建立到倒排索引中的;full text,会经历各种各样的处理,分词,normaliztion(时态转换,同义词转换,大小写转换,单复数转换),才会建立到倒排索引中;
(5)同时呢,exact value和full text类型的field就决定了,在一个搜索过来的时候,对exact value field或者是full text field进行搜索的行为也是不一样的,会跟建立倒排索引的行为保持一致;比如说exact value搜索的时候,就是直接按照整个值进行匹配,full text query string,也会进行分词和normalization再去倒排索引中去搜索;
(6)可以用es的dynamic mapping,让其自动建立mapping,包括自动设置数据类型;也可以提前手动创建index和type的mapping,自己对各个field进行设置,包括数据类型,包括索引行为,包括分词器,等等。
简单来说,mapping就是index的type的元数据,每个type都有一个自己的mapping,决定了数据类型,建立倒排索引的行为,还有进行搜索的行为。
手动创建mapping
只能创建index时手动建立mapping,或者新增field mapping,但是不能update field mapping
PUT /newwebsite
{
"mappings": {
"article": {
"properties": {
"author_id": {
"type": "long"
},
"title": {
"type": "text",
"analyzer": "english"
},
"content": {
"type": "text"
},
"post_date": {
"type": "date"
},
"publisher_id": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
测试修改analyzer为English
GET /newwebsite/_analyze
{
"field": "title",
"text": "a dog"
}
keyword,目前已经取代了 “index”: “not_analyzed”,另外,对于超过ignore_above 的字符串,analyzer 不会进行处理,不会索引起来,最终搜索引会擎搜索不到
分词
es中的分词器由三部分组成
1、character filter:作用:先对要进行分析的文本进行一下过滤,比如html文档,去除其中的标签,比如
、等等;
2、tokenizer:作用:对文本进行分词,把要进行分析的文本根据所指定的规则,按照其规则把文本拆分为单词,,只可以指定一个;
3、tokenizer filter:作用:把分好的词条(也即将tokenizer分好的词)进一步进行过滤,根据指定的filter把其识别的没用的词条给删除,或者增加(比如增加某些词的同义词)、修改(比如将testing、tested这种词同意为test)词条,可以指定多个。
[分词使用场景]:
- 创建或者更新文档时候,会对相应的文档进行分词处理
- 查询时,会对查询语句进行分词
- 注意,index时所用的分词器和查询时所用的分词器可不一样,可通过"analyzer"指定index时分词器,通过"search_analyzer"指定查询时分词器,但建议是设置成一样的,不然不利于查询(”put
test_index{“mappings”:{“doc”:{“properties”:{“title”:{“type”:“text”,“analyzer”:“whitespace”,“search_analyzer”:“standard”}}}}})
post _analyze
{
"analyzer":"stardard", #指定的分词器
"text":"hello world" #要进行分析的文本
}
post index_name/_analyze
{
"field":"firtname", #要进行分析的索引中的字段
"text":"ni cai" #要进行分析的文本
```perl
post _analyze
{
"tokenizer":"standard", #指定的分词器
"filter":["lowercase"], #对分析后的词最后进行小写转换
"text":"hello world" #要进行分析的文本
}
post _analyze
{
"tokenizer":"keyword",#指定的分词器,keyword分词不对要进行分析的文本划分为多个词条
"char_filter":["html_strip"], #指定的字符过滤器,这个html_strip过滤器会把文本中的html相关标签给去掉
"text":"<p>I'm so <b>happy</b>!</p> #要进行分析的文本
}
post _analyze
{
"tokenizer":"path_hierarchy", #指定的规则
"text":"/one/two/three" #要进行分析的文本