一、需求分析

注意: 本环境使用 elasticsearch 7.0版本开发,切勿低于此版本

mysql 表结构

有一张表,记录的数据特别的多,需要将7天前的记录,插入到Elasticsearch中,并删除原有表7天前的记录。

表结构如下:

CREATE TABLE `historic_records` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_id` varchar(50) NOT NULL DEFAULT '' COMMENT '用户id',
`time` bigint(20) NOT NULL DEFAULT '' COMMENT '上线/下线时间',
`create_time` bigint(20) NOT NULL DEFAULT '' COMMENT '创建时间',
`update_time` bigint(20) NOT NULL DEFAULT '' COMMENT '更新时间',
`online_status` tinyint(1) NOT NULL DEFAULT '' COMMENT '在线状态 默认1 0 离线 1 在线',
`status` tinyint(1) NOT NULL DEFAULT '' COMMENT '软删除标志:0-已删除;1-正常',
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `order_index` (`time`,`create_time`,`update_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='历史记录表';

查询sql:

select * from historic_records where create_time < unix_timestamp(date_add(cast(sysdate() as date), interval -7 day)) * 1000

删除sql:

delete from historic_records where create_time < unix_timestamp(date_add(cast(sysdate() as date), interval -7 day)) * 1000

ES中的一些概念

index(索引)

相当于mysql中的数据库

type(类型)

相当于mysql中的一张表

document(文档)

相当于mysql中的一行(一条记录)

field(域)

相当于mysql中的一列(一个字段)

节点

一个服务器,由一个名字来标识

集群

一个或多个节点组织在一起

分片

将一份数据划分为多小份的能力,允许水平分割和扩展容量。多个分片可以响应请求,提高性能和吞吐量。

副本

复制数据,一个节点出问题时,其余节点可以顶上。

倒排索引

可参考 https://www.elastic.co/guide/cn/elasticsearch/guide/current/inverted-index.html

es数据结构

设定映射,规定好各个字段及其数据类型,便于es更好地进行管理。根据mysql表结构,映射如下:

# 创建映射
_index_mappings = {
"settings": {
"index": {
"number_of_shards": 3,
"number_of_replicas": 1
}
},
"mappings": {
# self.index_type : {
"properties": {
"id": {"type": "long"},
"loid": {"type": "keyword"},
"mac": {"type": "keyword"},
"time": {
"type": "date",
"format": "epoch_millis"
},
"create_time": {
"type": "date",
"format": "epoch_millis"
},
"update_time": {
"type": "date",
"format": "epoch_millis"
},
"online_status": {"type": "short"},
"status": {"type": "short"}
}
# }
}
}

解释:

索引设置,都在 settings{...} 中

number_of_shards
每个索引的主分片数,默认值是 5 。这个配置在索引创建后不能修改。

number_of_replicas
每个主分片的副本数,默认值是 1 。对于活动的索引库,这个配置可以随时修改。

映射配置,都在mappings{...} 中

属性设置,都在 properties{...} 中

Elasticsearch 支持 如下简单域类型:

  • 字符串: string
  • 整数 : byteshortintegerlong
  • 浮点数: floatdouble
  • 布尔型: boolean
  • 日期: date

仔细看上面的mysql 表结构

由于 id 的类型是 bigint(20),那么在es中就是 long,表示长整形。

user_id 的类型是 varchar(50) ,在es中,有2中,分别是 text和 keyword。

这2种,是有区别的。text 会创建全文索引,支持模糊搜索。而keyword则不会,必须精确搜索才行。

由于 user_id不需要模糊搜索,因此 设置 keyword才是合理的。

create_time 虽然类型是 bigint(20),但是它存储在mysql里面,表示时间戳。

因此es中就是data,时间格式为:epoch_millis,表示微秒时间戳。

online_status 的类型是tinyint(1),在es中是 short,表示短的数字

三、elasticsearch和kibana搭建

elasticsearch

新建目录elasticsearch

mkdir /opt/elasticsearch-7.1.

目录结构如下:

./
├── dockerfile
├── elasticsearch-7.1.-amd64.deb
├── run.sh
└── sources.list

dockerfile

FROM ubuntu:16.04
# 修改更新源为阿里云
ADD sources.list /etc/apt/sources.list
ADD elasticsearch-7.1.-amd64.deb ./
# 安装jdk和elasticsearch
RUN apt-get update && apt-get install -y openjdk--jdk --allow-unauthenticated && apt-get clean all && dpkg -i elasticsearch-7.1.-amd64.deb && rm -rf elasticsearch-7.1.-amd64.deb
EXPOSE
# 添加启动脚本
ADD run.sh .
RUN chmod run.sh
ENTRYPOINT [ "/run.sh"]

run.sh

#!/bin/bash
set -e # 添加时区
TZ=Asia/Shanghai
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone # 覆盖配置文件
cp /etc/elasticsearch/elasticsearch.yml /etc/elasticsearch/elasticsearch.yml.bak
echo "transport.host: localhost
transport.tcp.port:
http.port:
network.host: 0.0.0.0" >> /etc/elasticsearch/elasticsearch.yml # 修改启动文件,去掉-d参数,避免后台运行
sed -i 's@-d -p $PID_FILE@-p $PID_FILE@g' /etc/init.d/elasticsearch # 启动elasticsearch,要hold住,否则容器启动就退出了!
/etc/init.d/elasticsearch start

sources.list

deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted
deb http://mirrors.aliyun.com/ubuntu/ xenial universe
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe
deb http://mirrors.aliyun.com/ubuntu/ xenial multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu xenial-security main restricted
deb http://mirrors.aliyun.com/ubuntu xenial-security universe
deb http://mirrors.aliyun.com/ubuntu xenial-security multiverse

生成镜像

docker build -t elasticsearch-7.1. .

启动容器

docker run -d -it --restart=always -p : elasticsearch-7.1.

访问页面

kibana

新建目录kibana

mkdir /opt/kibana-7.1.

目录结构如下:

./
├── dockerfile
├── kibana-7.1.-amd64.deb
└── run.sh

dockerfile

FROM ubuntu:16.04
ADD kibana-7.1.-amd64.deb ./
# 安装jdk和elasticsearch
RUN dpkg -i kibana-7.1.-amd64.deb && rm -rf kibana-7.1.-amd64.deb
EXPOSE
# 添加启动脚本
ADD run.sh .
RUN chmod run.sh
ENTRYPOINT [ "/run.sh"]

run.sh

#!/bin/bash

# 添加时区
TZ=Asia/Shanghai
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone #elasticsearch="192.168.91.128"
if [ -z $elasticsearch ];then
echo "elasticsearch参数为空!比如: 192.168.91.128"
exit
fi # 修改配置文件
# 修改监听地址
sed -i '7s@#server.host: "localhost"@server.host: "0.0.0.0"@g' /etc/kibana/kibana.yml
# 删除行,并添加一行内容
sed -i '28d' /etc/kibana/kibana.yml
sed -i "N;28 i elasticsearch.hosts: ["http://$elasticsearch:9200"]" /etc/kibana/kibana.yml # 启动
/usr/share/kibana/bin/kibana "-c /etc/kibana/kibana.yml"

生成镜像

docker build -t kibana-7.1. .

启动镜像

docker run -d -it --restart=always -p : -e elasticsearch=192.168.10.104 kibana-7.1.

访问页面

二、查询mysql数据

为了方便操作 mysql,封装了一个mysql工具类,用来查询和更新数据。

mysql.py

#!/usr/bin/env python3
# coding: utf-8 import pymysql class Mysql(object):
# mysql 端口号,注意:必须是int类型
def __init__(self,host,user,passwd,db_name,port=3306):
self.host = host
self.user = user
self.passwd = passwd
self.db_name = db_name
self.port = port def select(self,sql):
"""
执行sql命令
:param sql: 命令
:return: 元祖
"""
try:
conn = pymysql.connect(
host=self.host,
user=self.user,
passwd=self.passwd,
port=self.port,
database=self.db_name,
charset='utf8',
cursorclass=pymysql.cursors.DictCursor
)
cur = conn.cursor() # 创建游标
cur.execute(sql) # 执行sql命令
res = cur.fetchall() # 获取执行的返回结果
cur.close()
conn.close() # 关闭mysql 连接
return res
except Exception as e:
print(e)
return False def update(self,sql):
"""
更新操作,比如insert, delete,update
:param sql: sql命令
:return: bool
"""
try:
conn = pymysql.connect(
host=self.host,
user=self.user,
passwd=self.passwd,
port=self.port,
database=self.db_name,
)
cur = conn.cursor(cursor=pymysql.cursors.DictCursor) # 创建游标
# conn.cursor()
# print("ip: {} insert 执行命令: {}".format(self.host,sql))
sta = cur.execute(sql) # 执行sql命令,返回影响的行数
# print("sta",sta,type(sta))
#res = cur.fetchall() # 获取执行的返回结果
if isinstance(sta,int): # 判断返回结果, 是数字就是正常的
#print('插入记录 Done')
pass
# write_log('正常,远程执行sql: %s 成功'%sql, "green")
else:
write_log('错误,远程执行sql: %s 失败'%sql, "red")
return False conn.commit() # 主动提交,否则执行sql不生效
cur.close()
conn.close() # 关闭mysql 连接
return sta
except Exception as e:
print(e)
# write_log('错误,远程mysql执行命令: {} 异常'.format(sql), "red")
return False

使用时,就简单了。导入这个类,调用相关方法。

mysql_test.py

from mysql import Mysql

host = "192.168.0.179"
user = "sdn_db"
passwd = "Sdn@ujmyhn"
db_name = "terminalservice"
port = 3306 sql = "select * from terminals_record_0 where create_time < unix_timestamp(date_add(cast(sysdate() as date), interval -7 day)) * 1000"
res = Mysql(host,user,passwd,db_name,port).select(sql)
print(res)

三、完整代码

由于时间关系,代码不一一解释了。附上完整代码:

./
├── conf.py
├── es_bulk.py
├── README.md
├── requirements.txt
└── utils
├── common.py
└── mysql.py

conf.py

#!/usr/bin/env python3
# coding: utf-8
"""
配置文件,用于mysql和elasticsearch
"""
import os
BASE_DIR = os.path.dirname(os.path.abspath(__file__)) # 项目根目录 # mysql
HOST = "192.168.0.136"
USER = "root"
PASSWD = ""
DB_NAME = "terminal"
PORT = 3306 # elasticsearch
INDEX_NAME = "historic_records"
INDEX_TYPE = "_doc"
ES_IP = "192.169.3.133" MAXIMUM = 100 # 一次性插入多少条

es_bulk.py

#!/usr/bin/env python3
# coding: utf-8 import time
from elasticsearch import Elasticsearch
from elasticsearch import helpers import conf
from utils.mysql import Mysql
from utils.common import write_log,valid_ip,check_tcp class ElasticObj:
def __init__(self,timeout=3600):
'''
:param timeout: 超时时间
'''
self.index_name = conf.INDEX_NAME # 索引名称
self.index_type = conf.INDEX_TYPE # 索引类型
self.es_ip = conf.ES_IP # es ip # 无用户名密码状态
self.es = Elasticsearch([self.es_ip], port=9200, timeout=timeout)
# 用户名密码状态
# self.es = Elasticsearch([self.es_ip], http_auth=('esadm', 'mdase123'), port=9200, timeout=timeout) def create_index(self):
'''
创建索引
:return: bool
'''
# 创建映射
_index_mappings = {
# 索引配置
"settings": {
"index": {
"number_of_shards": 3, # 分片数
"number_of_replicas": 1 # 副本数
}
},
# 设置字段
"mappings": {
"properties": {
"id": {"type": "long"},
"loid": {"type": "keyword"},
"mac": {"type": "keyword"},
"time": {
"type": "date",
"format": "epoch_millis"
},
"create_time": {
"type": "date",
"format": "epoch_millis"
},
"update_time": {
"type": "date",
"format": "epoch_millis"
},
"online_status": {"type": "short"},
"status": {"type": "short"}
}
}
}
# 判断索引不存在时
if self.es.indices.exists(index=self.index_name) is not True:
# 创建索引
res = self.es.indices.create(index=self.index_name, body=_index_mappings)
# print(res)
if not res:
write_log("错误,创建索引{}失败".format(self.index_name),"red")
return False write_log("正常,创建索引{}成功".format(self.index_name), "green")
return True
else:
write_log("正常,索引{}已存在".format(self.index_name), "green")
return True def bulk_insert(self,table,data_list):
"""
批量写入数据
:param table: 表名
:param data_list: 数据列表
[
{
'online_status': 1,
'update_time': 1556073035327,
'create_time': 1556073035327,
'id': 1, 'status': 1,
'time': 1556073035327,
'loid': '100010000123',
'mac': '60:45:cb:87:c9:93'
},
...
]
:return: bool
"""
# 批量插入
start_time = time.time() # 开始时间
actions = [] # 临时数据列表
i = 0 # 计数值 try:
# 循环数据列表
for data in data_list:
action = {
"_index": self.index_name,
"_type": self.index_type,
#"_id": i, #_id 也可以默认生成,不赋值
"_source": {
'id': data['id'],
'user_id': data['user_id'],
'time': data['time'],
'create_time': data['create_time'],
'online_status': data['online_status'],
'status': data['status'],
}
}
i += 1
actions.append(action) # 添加到列表
if len(action) == conf.MAXIMUM: # 列表数量达到100时
helpers.bulk(self.es, actions) # 批量插入数据
del actions[0:len(action)] # 删除列表元素 if i > 0: # 不足100时,插入剩余数据
helpers.bulk(self.es, actions) end_time = time.time() # 结束时间
t = round((end_time - start_time),2) # 计算耗时
# print('本次共写入{}条数据,用时{}s'.format(i, t))
write_log("正常,{} 表写入ES {}条数据,用时{}s".format(table,i, t), "green")
return True
except Exception as e:
print(e)
return False def has_table(self,db_name,target_table):
"""
远程表是否存在
:return: bool
"""
mysql_obj = Mysql(conf.HOST, conf.USER, conf.PASSWD, conf.DB_NAME, conf.PORT)
sql = "select count(1) from {}.{}".format(db_name, target_table)
res = mysql_obj.select(sql)
# print("表是否存在",res,type(res)) if res is False:
write_log("错误,远程表 {}.{} 不存在".format(db_name,target_table),"red")
return False
else:
return True def has_conf(self):
"""
判断配置文件中的mysql和es 端口是否正常
:return:
"""
if not valid_ip(conf.HOST):
write_log("错误,MySQL IP配置不正确","red")
return False if not valid_ip(conf.ES_IP):
write_log("错误,ES IP配置不正确","red")
return False if not check_tcp(conf.HOST,conf.PORT):
write_log("错误,MySQL {} 端口不可达".format(conf.PORT),"red")
return False if not check_tcp(conf.ES_IP,9200):
write_log("错误,ES 9200 端口不可达","red")
return False return True def read_mysql_es(self):
"""
读取7天的记录,并写入es
:return: bool
"""
# 判断配置文件中的mysql和es 端口是否正常
if not self.has_conf():
# print(1)
return False # 创建索引
if self.create_index() is False:
# print(2)
return False max = conf.MAXIMUM # 一次性查询多少条 flag_list = [] # 标志位列表
mysql_obj = Mysql(conf.HOST, conf.USER, conf.PASSWD, conf.DB_NAME, conf.PORT)
for i in range(64): # 写入64张表
# 判断表是否存在
res = self.has_table(conf.DB_NAME,'historic_record_%s'%i)
if not res:
flag_list.append(False)
return False id = 0 # 每一次查询后的最大id
while True:
# 查询数据
sql = "select * from historic_record_%s where create_time < unix_timestamp(date_add(cast(sysdate() as date), interval -7 day)) * 1000 and id > %s order by id limit %s" % (
i, id, max)
# print(sql)
data_list = mysql_obj.select(sql)
# print(data_list)
if not data_list: # 当结果为空时,结束循环
write_log("警告,执行sql: %s 记录为空,无需写入es" %(sql), "yellow")
break # 跳出循环 last_row = data_list[-1] # 最后一行记录
# print(last_row)
id = last_row['id'] # 修改最大id res = self.bulk_insert('historic_record_%s' % i, data_list)
if not res:
write_log("错误,historic_record_%s 写入ES 失败"%i,"red")
flag_list.append(False)
return False if False in flag_list:
write_log("错误,historic_record 部分表写入ES错误,请查看上文","red")
return False write_log("正常,historic_record 64张表全部写入ES成功", "green")
return True def delete_record(self):
"""
删除7天的表数据
:return: bool
"""
max = conf.MAXIMUM # 一次性查询多少条
flag_list = []
mysql_obj = Mysql(conf.HOST, conf.USER, conf.PASSWD, conf.DB_NAME, conf.PORT)
for i in range(64): # 64张表
# 判断表是否存在
res = self.has_table(conf.DB_NAME, 'historic_record_%s' % i)
if not res:
flag_list.append(False)
return False ### 先查询数据
id = 0 # 每一次查询后的最大id
while True:
# 查询数据
sql = "select * from historic_record_%s where create_time < unix_timestamp(date_add(cast(sysdate() as date), interval -7 day)) * 1000 and id > %s order by id limit %s" % (
i, id, max)
# print(sql)
data_list = mysql_obj.select(sql)
# print(data_list)
if not data_list: # 当结果为空时,结束循环
write_log("警告,执行sql: %s 记录为空,无需删除" % sql, "yellow")
break # 跳出循环 ### 再删除数据
sql = "delete from historic_record_%s where create_time < unix_timestamp(date_add(cast(sysdate() as date), interval -7 day)) * 1000 and id > %s order by id limit %s" % (
i, id, max)
# print(sql)
res = mysql_obj.update(sql)
if res is False:
write_log("错误,删除 historic_record_%s 记录失败" % i, "red")
flag_list.append(False)
break
else:
write_log("正常,删除 historic_record_%s 记录成功" % i, "green") last_row = data_list[-1] # 最后一行记录
# print(last_row)
id = last_row['id'] # 修改最大id if False in flag_list:
write_log("错误,删除 historic_record 部分表失败,请查看上文", "red")
return False write_log("正常,删除 historic_record 64张表记录全部成功", "green") def main(self):
self.read_mysql_es()
self.delete_record() ElasticObj().main() # 执行主程序

common.py

#!/usr/bin/env python3
# coding: utf-8
"""
共有的方法
""" import sys
import io def setup_io(): # 设置默认屏幕输出为utf-8编码
sys.stdout = sys.__stdout__ = io.TextIOWrapper(sys.stdout.detach(), encoding='utf-8', line_buffering=True)
sys.stderr = sys.__stderr__ = io.TextIOWrapper(sys.stderr.detach(), encoding='utf-8', line_buffering=True)
setup_io() import os
import time
import conf
import socket
import subprocess
import ipaddress
from multiprocessing import cpu_count def write_log(content,colour='white',skip=False):
"""
写入日志文件
:param content: 写入内容
:param colour: 颜色
:param skip: 是否跳过打印时间
:return:
"""
# 颜色代码
colour_dict = {
'red': 31, # 红色
'green': 32, # 绿色
'yellow': 33, # 黄色
'blue': 34, # 蓝色
'purple_red': 35, # 紫红色
'bluish_blue': 36, # 浅蓝色
'white': 37, # 白色
}
choice = colour_dict.get(colour) # 选择颜色 path = os.path.join(conf.BASE_DIR,"output.log") # 日志文件
with open(path, mode='a+', encoding='utf-8') as f:
if skip is False: # 不跳过打印时间时
content = time.strftime('%Y-%m-%d %H:%M:%S') + ' ' + content info = "\033[1;{};1m{}\033[0m".format(choice, content)
print(info)
f.write(content+"\n") def execute_linux2(cmd, timeout=10, skip=False):
"""
执行linux命令,返回list
:param cmd: linux命令
:param timeout: 超时时间,生产环境, 特别卡, 因此要3秒
:param skip: 是否跳过超时
:return: list
"""
p = subprocess.Popen(cmd, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, shell=True)
# print(p)
# timeout = 1 # 超时时间
t_beginning = time.time() # 开始时间
# seconds_passed = 0 # 执行时间
while True:
if p.poll() is not None:
break
seconds_passed = time.time() - t_beginning
if timeout and seconds_passed > timeout:
p.terminate()
# raise TimeoutError(cmd, timeout)
if not skip:
# self.res.code = 500
# print('命令: {},执行超时!'.format(cmd))
write_log('错误, 命令: {},本地执行超时!'.format(cmd),"red")
# return self.res.__dict__
return False
# return '命令: {},执行超时!'.format(cmd) # result = p.stdout.read().decode('utf-8').strip() # 命令运行结果
# print("result",result)
# self.res.data = result
# return self.res.__dict__
result = p.stdout.readlines()
return result def valid_ip(ip):
"""
验证ip是否有效,比如192.168.1.256是一个不存在的ip
:return: bool
"""
try:
# 判断 python 版本
if sys.version_info[0] == 2:
ipaddress.ip_address(ip.strip().decode("utf-8"))
elif sys.version_info[0] == 3:
# ipaddress.ip_address(bytes(ip.strip().encode("utf-8")))
ipaddress.ip_address(ip) return True
except Exception as e:
print(e)
return False def check_tcp(ip, port, timeout=1):
"""
检测tcp端口
:param ip: ip地址
:param port: 端口号
:param timeout: 超时时间
:return: bool
"""
flag = False
try:
socket.setdefaulttimeout(timeout) # 整个socket层设置超时时间
cs = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
address = (str(ip), int(port))
status = cs.connect_ex((address)) # 开始连接
cs.settimeout(timeout) if not status:
flag = True return flag
except Exception as e:
print(e)
return flag COROUTINE_NUMBER = cpu_count() # 协程池数量,根据cpu核心数来开,避免cpu飙高

mysql.py

#!/usr/bin/env python3
# coding: utf-8 import pymysql
from utils.common import write_log class Mysql(object):
# mysql 端口号,注意:必须是int类型
def __init__(self,host,user,passwd,db_name,port=3306):
self.host = host
self.user = user
self.passwd = passwd
self.db_name = db_name
self.port = port def select(self,sql):
"""
执行sql命令
:param sql: 命令
:return: 元祖
"""
try:
# print(host,self.user,self.passwd,self.port,self.db_name)
conn = pymysql.connect(
host=self.host,
user=self.user,
passwd=self.passwd,
port=self.port,
database=self.db_name,
charset='utf8',
cursorclass=pymysql.cursors.DictCursor
)
cur = conn.cursor() # 创建游标
# conn.cursor()
cur.execute(sql) # 执行sql命令
res = cur.fetchall() # 获取执行的返回结果
cur.close()
conn.close() # 关闭mysql 连接
return res
except Exception as e:
print(e)
return False def update(self,sql):
"""
更新操作,比如insert, delete,update
:param sql: sql命令
:return: bool
"""
try:
conn = pymysql.connect(
host=self.host,
user=self.user,
passwd=self.passwd,
port=self.port,
database=self.db_name,
)
cur = conn.cursor(cursor=pymysql.cursors.DictCursor) # 创建游标
# conn.cursor()
# print("ip: {} insert 执行命令: {}".format(self.host,sql))
sta = cur.execute(sql) # 执行sql命令,返回影响的行数
# print("sta",sta,type(sta))
#res = cur.fetchall() # 获取执行的返回结果
if isinstance(sta,int): # 判断返回结果, 是数字就是正常的
#print('插入记录 Done')
pass
# write_log('正常,远程执行sql: %s 成功'%sql, "green")
else:
write_log('错误,远程执行sql: %s 失败'%sql, "red")
return False conn.commit() # 主动提交,否则执行sql不生效
cur.close()
conn.close() # 关闭mysql 连接
#Migration.flag_list.append(True)
return sta
except Exception as e:
print(e)
# write_log('错误,远程mysql执行命令: {} 异常'.format(sql), "red")
# Migration.flag_list.append(False)
return False

requirements.txt

PyMySQL==0.9.2
elasticsearch==6.3.1

README.md

## 说明
终端历史记录表,写入到elasticsearch中。 主要将(terminal.historic_record_0~63) 这64张表的7天前数据写入到elasticsearch中 并删除 64张表的7天前记录 `注意: 本环境使用 elasticsearch 7.0版本开发,切勿低于此版本` ## 配置说明
`conf.py` 是环境配置 主要修改 以下信息
```python
# mysql
HOST = "192.168.0.136"
USER = "root"
PASSWD = ""
DB_NAME = "terminal"
PORT = 3306 # elasticsearch
INDEX_NAME = "historic_record"
INDEX_TYPE = "_doc"
ES_IP = "192.169.3.133"
``` 请根据实际情况修改以上变量 ## 运行说明
## 一键执行,迁移相关所有表
`python es_bulk.py` ## 查看结果
结果会输出到`output.log`文件,直接查看即可! 登录到`kibana`,查看数据是否存在 <br/>
<br/>
Copyright (c) 2019-present, xiao You

注意:如果是es 6.x的版本,创建索引,需要增加 index_type,否则会报错。

比如:

# 创建映射
_index_mappings = {
# 索引配置
"settings": {
"index": {
"number_of_shards": 3, # 分片数
"number_of_replicas": 1 # 副本数
}
},
# 设置字段
"mappings": {
self.index_type: {
"properties": {
"id": {"type": "long"},
"loid": {"type": "keyword"},
"mac": {"type": "keyword"},
"time": {
"type": "date",
"format": "epoch_millis"
},
"create_time": {
"type": "date",
"format": "epoch_millis"
},
"update_time": {
"type": "date",
"format": "epoch_millis"
},
"online_status": {"type": "short"},
"status": {"type": "short"}
}
}
}
}

本文参考链接:

https://www.cnblogs.com/aaanthony/p/7380662.html

https://blog.csdn.net/m0_37673307/article/details/81153700

python MySQL 插入Elasticsearch的更多相关文章

  1. Python MySQL 插入表

    章节 Python MySQL 入门 Python MySQL 创建数据库 Python MySQL 创建表 Python MySQL 插入表 Python MySQL Select Python M ...

  2. python mysql插入数据遇到的错误

    1.数据插入的时候报错:not enough arguments for format string,大概意思就是说没有足够的参数格式化字符串. 我的数据库插入方法是这样的 def add_data( ...

  3. python mysql插入中文乱码

    # "INSERT INTO" 语句sql = "INSERT INTO sites (name, url, status, enable) VALUES (%s, %s ...

  4. python mysql插入多条数据

    #!/usr/bin/env python # encoding: utf-8 import pymysql from config.config import * import datetime d ...

  5. Python MongoDB 插入文档

    章节 Python MySQL 入门 Python MySQL 创建数据库 Python MySQL 创建表 Python MySQL 插入表 Python MySQL Select Python M ...

  6. Python MySQL Join

    章节 Python MySQL 入门 Python MySQL 创建数据库 Python MySQL 创建表 Python MySQL 插入表 Python MySQL Select Python M ...

  7. Python MySQL Update

    章节 Python MySQL 入门 Python MySQL 创建数据库 Python MySQL 创建表 Python MySQL 插入表 Python MySQL Select Python M ...

  8. Python MySQL Limit

    章节 Python MySQL 入门 Python MySQL 创建数据库 Python MySQL 创建表 Python MySQL 插入表 Python MySQL Select Python M ...

  9. Python MySQL 删除表

    章节 Python MySQL 入门 Python MySQL 创建数据库 Python MySQL 创建表 Python MySQL 插入表 Python MySQL Select Python M ...

随机推荐

  1. 20-ESP8266 SDK开发基础入门篇--C# TCP客户端编写 , 加入数据通信

    https://www.cnblogs.com/yangfengwu/p/11192594.html 自行调整页面 连接上以后主动发个数据 namespace TCPClient { public p ...

  2. PHP正则表达式提取html超链接中的href地址

    $preg='/<a .*?href="(.*?)".*?>/is'; preg_match_all($preg,$str,$array2); ;$i<count ...

  3. Web前端鼠标悬停实现显示与隐藏效果

    css定义,偏移量,相对定位,绝对定位 显示与隐藏 二维码相对于微信图标定位 鼠标悬停微信图标上显示 鼠标离开微信图标时隐藏 什么是定位,就是定义网页标签在运行时显示的位置 css提供Position ...

  4. C博客作业01——分支,顺序结构

    C博客作业01--分支,顺序结构 0.展示PTA总分 1本章学习内容 1.1学习内容总结 1)格式化输出函数printf(),scanf(). 它是什么? 对于初学者而言,一开始了解接触它们,只是被硬 ...

  5. 龙贝格积分(c++)

    用龙贝格算法计算积分 #include <iostream> #include<cmath> #include <iomanip> using namespace  ...

  6. 【算法编程 C++ python】单链表反序输出

    题目描述 输入一个链表,从尾到头打印链表每个节点的值.   以下方法仅仅实现了功能,未必最佳.在牛客网测试, C++:3ms 480k Python:23ms 5732k /** * struct L ...

  7. [C++] namespace命名空间和using用法

    命名空间namespace:指标识符的各种可见范围. C++标准程序库中的所有标识符都被定义在一个std的namespace,这就是程序开始添加 using namespace std; 的原因. 很 ...

  8. 自定义Spring Boot内置tomcat的404页面

    spring boot 的相关404页面配置都是针对项目路径下的(如果配置了 context-path) 在context-path不为空的情况下,如果访问路径不带context-path,这时候会显 ...

  9. vue---发送数据请求的一些列的问题

    使用vue做数据请求,首先考虑的是封装请求方法request.js import axios from 'axios' import Qs from 'qs' // 创建一个axios实例 const ...

  10. Python3基础 函数 __name__ 得到引用所指向的真正名字

             Python : 3.7.3          OS : Ubuntu 18.04.2 LTS         IDE : pycharm-community-2019.1.3    ...