有了索引库,等于有了数据库中的 database。接下来就需要建索引库(index)中的映射了,类似于数据库(database)中的表结构(table)。
创建数据库表需要设置字段名称,类型,长度,约束等;索引库也一样,需要知道这个类型下有哪些字段,每个字段有哪些约束信息,这就叫做映射(mapping)。
在 Postman 中,向 ES 服务器发 PUT 请求 :http://127.0.0.1:9200/student/_mapping
(在创建隐射之前应先保证 student
已经创建成功)
{
"properties": {
"name":{
"type": "text",
"index": true
},
"sex":{
"type": "text",
"index": true
},
"age":{
"type": "long",
"index": true
}
}
}
隐射数据说明:
字段名:任意填写
type:类型,Elasticsearch 支持的数据类型
index 是否索引,默认为 true,表示该字段可以被索引
store:是否将数据进行独立存储,默认为 false
原始的文本会存储在_source
里面,默认情况下其他提取出来的字段都不是独立存储的,是从 _source
里面提取出来的。当然你也可以独立的存储某个字段,只要设置 "store": true
即可,获取独立存储的字段要比从 _source
中解析快得多,但是也会占用更多的空间,所以要根据实际业务需求来设置。
http://127.0.0.1:9200/student1
,传入json数据如下即在body中定义mappings
用来关联相应的隐射:{
"settings": {},
"mappings": {
"properties": {
"name":{
"type": "text",
"index": true
},
"sex":{
"type": "text",
"index": false
},
"age":{
"type": "long",
"index": false
}
}
}
}
如图所示, 第二象限是一份原始文档,有 title 和 content 2个字段,字段取值分别为”我是中国人”和” 热爱共产党”。我们把原始文档写入Elasticsearch,默认情况下,Elasticsearch里面有2份内容。
一份是 倒排索引,倒排索引中的数据结构是倒排记录表,记录了词项和文档之间的对应关系,比如关键词”中国人”包含在文档ID为1的文档中,倒排记录表中存储的就是这种对应关系,当然也包括词频等更多信息。
如果先要关闭 source 字段,设置如下:
{
"yourtype":{
"_source":{
"enabled":false
},
"properties": {
...
}
}
}
如果只想存储某几个字段的原始值到Elasticsearch,可以通过incudes参数来设置,在mapping中的设置如下:
{
"yourtype":{
"_source":{
"includes":["field1","field2"]
},
"properties": {
...
}
}
}
同样,可以通过excludes参数排除某些字段:
{
"yourtype":{
"_source":{
"excludes":["field1","field2"]
},
"properties": {
...
}
}
}
_all
字段里面包含了一个文档里面的所有信息,是一个超级字段。以图中的文档为例,如果开启_all
字段,那么title+content
会组成一个超级字段,这个字段包含了其他字段的所有内容,当然也可以设置只存储某几个字段到_all
属性里面或者排除某些字段。_all
字段{
"yourtype": {
"_all": {
"enabled": true
},
"properties": {
...
}
}
}
_all
字段{
"yourtype": {
"properties": {
"field1": {
"type": "string",
"include_in_all": false
},
"field2": {
"type": "string",
"include_in_all": true
}
}
}
}
es 的 store 表示是否存储该字段。不存储的话无法展示。默认的store
属性就是 no
,然而我们依然能够检索出所有的字段,原因是还有一个 _source
字段,这个字段存储了我们 index
的时候的全部属性,所以我们可以通过解析 `source来获得里面的字段,如果我们不指定field的话,甚至不需要解析直接返回整个source。
store = yes 会对这个字段做单独存储,es除了构建倒排索引,还会构建一个存储域,倒排索引用来做查询命中文档id,存储域用来存放写入的具体文档.
如果store=yes则是将这个 field 单独存储到一个存储域中,因此使用field获取字段的时候不走source,会去额外的区域获取字段值. 当然我们也可以指定从哪个区域取:
GET my_index/_search
{
"stored_fields": [ "title", "date" ]
}
可以理解为 store=yes,其实就是用一个新的空间来存储某个字段内容,方便检索时直接返回。避免了从source中进行全局的搜索
注意: 如果想要对某个字段实现高亮功能,_source
和store
至少保留一个。下面会给出测试代码。
如果将 _all
字段进行存储:
PUT test/test/_mapping
{
"test": {
"_all": {
"enabled": true,
"store": true
}
}
}
利用 source中的 all 完成高亮搜索
POST test/test/1
{
"title":"我是中国人",
"content":"热爱共产党"
}
_all
进行搜索并且高亮POST test/_search
{
"fields": ["_all"],
"query": {
"match": {
"_all": "中国人"
}
},
"highlight": {
"fields": {
"_all": {}
}
}
}
结果如下: {
"took": 3,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.15342641,
"hits": [
{
"_index": "test",
"_type": "test",
"_id": "1",
"_score": 0.15342641,
"_all": "我是中国人 热爱共产党 ",
"highlight": {
"_all": [
"我是中国人 热爱共产党 "
]
}
}
]
}
}
GET test/_search
{
"query": {
"query_string": {
"query": "共产党"
}
}
}
利用 store 完成高亮搜索
_source
且添加字段的store属性为 true,即用单独的空间进行存储DELETE test
PUT test
PUT test/test/_mapping
{
"test": {
"_source": {
"enabled": false
},
"properties": {
"title": {
"type": "string",
"index": "not_analyzed",
"store": "true"
},
"content": {
"type": "string"
}
}
}
}
GET test/_search
{
"query": {
"match": {
"title": "我是中国人"
}
},
"highlight": {
"fields": {
"title": {}
}
}
}
{
"took": 6,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.30685282,
"hits": [
{
"_index": "test",
"_type": "test",
"_id": "1",
"_score": 0.30685282,
"highlight": {
"title": [
"我是中国人"
]
}
}
]
}
}
# POST /student/_doc/1001
{
"name":"zhangsan",
"nickname":"zhangsan",
"sex":"男",
"age":30
}
# POST /student/_doc/1002
{
"name":"lisi",
"nickname":"lisi",
"sex":"男",
"age":20
}
# POST /student/_doc/1003
{
"name":"wangwu",
"nickname":"wangwu",
"sex":"女",
"age":40
}
# POST /student/_doc/1004
{
"name":"zhangsan1",
"nickname":"zhangsan1",
"sex":"女",
"age":50
}
# POST /student/_doc/1005
{
"name":"zhangsan2",
"nickname":"zhangsan2",
"sex":"女",
"age":30
}
{
"query": {
"match_all": {}
}
}
# "query":这里的 query 代表一个查询对象,里面可以有不同的查询属性
# "match_all":查询类型,例如:match_all(代表查询所有), match,term , range 等等
# {查询条件}:查询条件会根据类型的不同,写法也有差异
{
"took【查询花费时间,单位毫秒】" : 1116,
"timed_out【是否超时】" : false,
"_shards【分片信息】" : {
"total【总数】" : 1,
"successful【成功】" : 1,
"skipped【忽略】" : 0,
"failed【失败】" : 0
},
"hits【搜索命中结果】" : {
"total"【搜索条件匹配的文档总数】: {
"value"【总命中计数的值】: 3,
"relation"【计数规则】: "eq" # eq 表示计数准确, gte 表示计数不准确
},
"max_score【匹配度分值】" : 1.0,
"hits【命中结果集合】" : [
。。。
}
]
}
}
http://127.0.0.1:9200/student/_search
{
"query":{
"match":{
"name":"zhangsan"
}
}
}
multi_match 与 match 类似,不同的是它可以在多个字段中查询。 - 在 Postman 中,向 ES 服务器发 POST 请求 :http://127.0.0.1:9200/student/_search
{
"query": {
"multi_match": {
"query": "zhangsan",
"fields": ["name","nickname"]
}
}
}
即查询name or nickname 中的 zhangsan
http://127.0.0.1:9200/student/_search
{
"query": {
"term": {
"name": {
"value": "zhangsan1"
}
}
}
}
http://127.0.0.1:9200/student/_search
{
"_source": ["name","nickname"],
"query": {
"terms": {
"nickname": ["zhangsan","zhangsan1"]
}
}
}
http://127.0.0.1:9200/student/_search
{
"_source": {
"includes": ["name","nickname"]
},
"query": {
"terms": {
"nickname": ["zhangsan"]
}
}
}
结果如下:exclude
请求,想ES 服务器发送 POST 请求: http://127.0.0.1:9200/student/_search
{
"_source": {
"excludes": ["name","nickname"]
},
"query": {
"terms": {
"nickname": ["zhangsan"]
}
}
}
结果如下:bool
把各种其它查询通过must
(必须 )、must_not
(必须不)、should
(应该)的方式进行组合http://127.0.0.1:9200/student/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "zhangsan"
}
}
],
"must_not": [
{
"match": {
"age": "40"
}
}
],
"should": [
{
"match": {
"sex": "男"
}
}
]
}
}
}
range 查询找出那些落在指定区间内的数字或者时间。range 查询允许以下字符:
作符 | 说明 |
---|---|
t | 大于 > |
te | 大于等于 >= |
t | 小于 < |
te | 小于等于 <= |
则向ES发送POST请求:http://127.0.0.1:9200/student/_search
{
"query": {
"range": {
"age": {
"gte": 30,
"lte": 35
}
}
}
}
fuzziness
来衡量词与词之间的相似度,利用 fuzzy
返回一定编辑距离内的字词文档。http://127.0.0.1:9200/student/_search
{
"query": {
"fuzzy": {
"title": {
"value": "zhangsan"
}
}
}
}
{
"query": {
"fuzzy": {
"name": {
"value": "zhangsan",
"fuzziness": 2
}
}
}
}
sort 可以让我们按照不同的字段进行排序,并且通过 order 指定排序的方式。desc 降序,asc升序
。
http://127.0.0.1:9200/student/_search
{
"query": {
"match": {
"name":"zhangsan"
}
},
"sort": [{
"age": {
"order":"desc"
}
}]
}
//http://127.0.0.1:9200/student/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"age": {
"order": "desc"
}
},
{
"_score":{
"order": "desc"
}
}
]
}
//post: http://127.0.0.1:9200/student/_search
{
"query": {
"match": {
"name": "zhangsan"
}
},
"highlight": {
"pre_tags": "",
"post_tags": "",
"fields": {
"name": {}
}
}
}
from = (pageNum - 1) * size
{
"query": {
"match_all": {}
},
"sort": [
{
"age": {
"order": "desc"
}
}
],
"from": 0,
"size": 2
}
聚合允许使用者对 es 文档进行统计分析,类似与关系型数据库中的 group by
,当然还有很多其他的聚合,例如取最大值、平均值等等。
//:http://127.0.0.1:9200/student/_search
{
"aggs":{
"max_age":{
"max":{"field":"age"}
}
},
"size":0
}
//http://127.0.0.1:9200/student/_search
{
"aggs":{
"min_age":{
"min":{"field":"age"}
}
},
"size":0
}
//http://127.0.0.1:9200/student/_search
{
"aggs":{
"sum_age":{
"sum":{"field":"age"}
}
},
"size":0
}
{
"aggs":{
"avg_age":{
"avg":{"field":"age"}
}
},
"size":0
}
//对某个字段的值进行去重之后再取总数
{
"aggs":{
"distinct_age":{
"cardinality":{"field":"age"}
}
},
"size":0
}
count,max,min,avg 和 sum
五个指标//http://127.0.0.1:9200/student/_search
{
"aggs":{
"stats_age":{
"stats":{"field":"age"}
}
},
"size":0
}