ElasticSearch允许我们对一个索引进行字段的新增, 但是不允许我们更改字段的类型或删除一个字段,因为这里面涉及到原有字段在创建的时候已经内部落实了倒排索引等工作,变更原有字段或删除已有字段会导致搜索不能正常工作。
下面依次按照我操作的思路和方法落实:
- 创建一个索引(仅含映射, 不含文档)
- 写入一些数据(文档)
- 增加一个字段(property)
- 修改一个字段的辅助属性(例如date的format)
- 修改或删除一个字段(这里有说明没办法做这个事情)
- 通过重新索引来达到我们对已有字段变更的目的(re-index)
创建一个索引(仅含映射, 不含文档)
# -.- coding:utf-8 -.-
from elasticsearch import Elasticsearch
from pprint import pprint
es = Elasticsearch(hosts=["192.168.1.132"])
s = es.indices.create(
index="web_system",
body={
"mappings": {
"user": {
"properties": {
"nickname": {
"type": "string"
},
"username": {
"type": "string"
},
"join_date": {
"type": "date",
"format": "strict_date_hour_minute_second_millis"
},
"description": {
"type": "string",
"analyzer": "english"
}
}
}
}
}
)
pprint(s)
写入一些数据(文档)
# -.- coding:utf-8 -.-
from elasticsearch import Elasticsearch
from pprint import pprint
es = Elasticsearch(hosts=["192.168.1.132"])
# 单条写入
s = es.index(
index="web_system",
doc_type="user",
id="1",
body={
"username": "张三",
"nickname": "弓长III"
}
)
pprint(s)
# 多条写入(批量)
s = es.bulk(
index="web_system",
doc_type="user",
body=[
{"create": {"_id": 2}},
{"username": "李四", "nickname": "木子IV"},
{"create": {"_id": 3}},
{"username": "王五", "nickname": "钻石V"}
]
)
pprint(s)
增加一个字段(property)
# -.- coding:utf-8 -.-
from elasticsearch import Elasticsearch
from pprint import pprint
es = Elasticsearch(hosts=["192.168.1.132"])
s = es.indices.put_mapping(
index="web_system",
doc_type="user",
body={
"properties": {
"age": {
"type": "integer",
}
}
}
)
pprint(s)
修改一个字段的辅助属性(例如date的format)
# -.- coding:utf-8 -.-
# 内置日期格式, 请参考这里:
# https://www.elastic.co/guide/en/elasticsearch
# /reference/current/mapping-date-format.html#built-in-date-formats
from elasticsearch import Elasticsearch
from pprint import pprint
es = Elasticsearch(hosts=["192.168.1.132"])
s = es.indices.put_mapping(
index="web_system",
doc_type="user",
body={
"properties": {
"date_join": {
"type": "date",
"format": "yyyy-MM-dd",
},
}
}
)
pprint(s)
查看现在的索引信息
# -.- coding:utf-8 -.-
from elasticsearch import Elasticsearch
from pprint import pprint
es = Elasticsearch(hosts=["192.168.1.132"])
s = es.indices.get_mapping(
index="web_system",
doc_type="user"
)
pprint(s)
# 输出结果
{'web_system': {
'mappings': {
'user': {
'properties': {
'age': {'type': 'string'},
'description': {'analyzer': 'english', 'type': 'string'},
'join_date': {'format': 'strict_date_hour_minute_second_millis', 'type': 'date'},
'nickname': {'type': 'string'},
'username': {'type': 'string'}
}
}
}
}}
重新索引(re-index)
先建立一个别名
# -.- coding:utf-8 -.-
from elasticsearch import Elasticsearch
from pprint import pprint
es = Elasticsearch(hosts=["192.168.1.132"])
es.indices.put_alias(
index="web_system",
name="w_s",
)
然后再建立一个新的索引结构
# -.- coding:utf-8 -.-
from elasticsearch import Elasticsearch
from pprint import pprint
es = Elasticsearch(hosts=["192.168.1.132"])
s = es.indices.create(
index="web_system2", # 这里定义个新的索引名称
body={
"mappings": {
"user": {
"properties": {
# 将age字段的string类型值更改为integer类型
"age": {"type": "integer"},
# 这里定义一个新的分析器
"description": {"type": "string", "analyzer": "standard"},
"join_date": {"format": "strict_date_hour_minute_second_millis", "type": "date"},
# 这里声明该字段是一个精确值, 而不是一个分析器
"nickname": {"type": "string", "index": "not_analyzed"},
# 这里声明该字段是一个精确值, 而不是一个分析器
"username": {"type": "string", "index": "not_analyzed"}
}
}
}
}
)
pprint(s)
然后开始迁移数据
数据迁移可以有两种方式(二选一即可), 第一种方式是自己读取出数据,然后写入到新的索引中; 第二种方式是利用re-index api来让内部帮我们完成这个过程, 下面分别列出两种写法.
第一种方式
# -.- coding:utf-8 -.-
from elasticsearch import Elasticsearch
from elasticsearch import helpers
from pprint import pprint
es = Elasticsearch(hosts=["192.168.1.132"])
# 读取所有文档
s = es.search(
index="web_system",
doc_type="user",
scroll="1m",
body={
"size": 10000,
"query": {
"match_all": {}
}
},
filter_path=['hits.hits._*']
)
# 更新所有返回文档中的索引名称
for enum, i in enumerate(s["hits"]["hits"]):
s["hits"]["hits"][enum]["_index"] = "web_system2"
# 将所有文档写入到新的索引中
b = helpers.bulk(
client=es,
actions=s["hits"]["hits"]
)
pprint(b)
第二种方式
# -.- coding:utf-8 -.-
from elasticsearch import Elasticsearch
from pprint import pprint
es = Elasticsearch(hosts=["192.168.1.132"])
s = es.reindex(
body={
"source": {
"index": "web_system"
},
"dest": {
"index": "web_system2"
}
}
)
pprint(s)
最后切换别名
# -.- coding:utf-8 -.-
from elasticsearch import Elasticsearch
from pprint import pprint
es = Elasticsearch(hosts=["192.168.1.132"])
# 更新别名
s = es.indices.update_aliases(
body={
"actions": [
{"remove": {"index": "web_system", "alias": "w_s"}},
{"add": {"index": "web_system2", "alias": "w_s"}}
]
}
)
# 删除老的索引
es.indices.delete(
index="web_system"
)
pprint(s)
数据迁移后
在之前所有数据的查询,都是使用真是的索引名称,当我们做了索引迁移之后,删除了老的索引名称,只有能根据新的索引名称或者索引别名来查询数据了。
也就是说在项目一开始的时候就建议使用索引别名,这样贯穿全生命周期都不需要更改任何代码。
这里列出通过别名来查询数据.
# -.- coding:utf-8 -.-
from elasticsearch import Elasticsearch
from pprint import pprint
es = Elasticsearch(hosts=["192.168.1.132"])
s = es.search(
index="w_s",
doc_type="user",
body={
"query": {
"match_all": {}
}
}
)
pprint(s["hits"]["hits"])
# 输出结果
[{'_id': '2',
'_index': 'web_system2',
'_score': 1.0,
'_source': {'age': '24',
'description': 'he is very busy',
'nickname': '木子IV',
'username': '李四'},
'_type': 'user'},
{'_id': '1',
'_index': 'web_system2',
'_score': 1.0,
'_source': {'age': '23',
'description': 'this gay is very lazy.',
'nickname': '弓长III',
'username': '张三'},
'_type': 'user'},
{'_id': '3',
'_index': 'web_system2',
'_score': 1.0,
'_source': {'age': '35',
'description': 'the boss of our company',
'nickname': '钻石V',
'username': '王五'},
'_type': 'user'}]
参考
- [x] 重新索引
- [x] re-index api
- [x] 索引别名和零停机
- [x] 映射
网友评论