Python & Spark 操作常见数据库整理

Python

mysql

使用pymysql操作,连接主要配置参数:
config = {
'host': "host",
'port': 3306,
'database': "database",
'user': "user",
'password': "password"
}

# 使用pymysql库。
import pymysql

# 配置连接参数
config = {
    'host': "host",
    'port': 3306,
    'database': "database",
    'user': "user",
    'password': "password"
}


# 连接mysql
def mysql_conn(config):
    conn = pymysql.connect(**config)
    return conn


# mysql操作,查询
def get_mysql_data(conn, query: str):
    # 先创建cursor负责操作conn接口
    cursor = conn.cursor()
    try:
        # 执行sql操作,可以使用executemany批量操作
        cursor.execute(query)
        # 返回多个元组,即返回多条记录(rows),如果没有结果,则返回 (),fetchone返回单个记录。
        res = cursor.fetchall()
        cursor.close()
        conn.close()
    except Exception as e:
        print("mysql查询失败")
        cursor.close()
        conn.close()
    return res

# mysql操作,插入


def insert_data(conn, df):
    # 先创建cursor负责操作conn接口
    cursor = conn.cursor()
    # 先构造需要的或是和数据库相匹配的列
    columns = list(df.columns)
    # 可以删除不要的列或者数据库没有的列名
    columns.remove("列名")
    # 重新构造df,用上面的columns,到这里你要保证你所有列都要准备往数据库写入了
    new_df = df[columns].copy()

    # 构造符合sql语句的列,因为sql语句是带有逗号分隔的,(这个对应上面的sql语句的(column1, column2, column3))
    columns = ','.join(list(new_df.columns))

    # 构造每个列对应的数据,对应于上面的((value1, value2, value3))
    data_list = [tuple(i) for i in new_df.values]  # 每个元组都是一条数据,根据df行数生成多少元组数据

    # 计算一行有多少value值需要用字符串占位
    s_count = len(data_list[0]) * "%s,"

    # 构造sql语句
    insert_sql = "insert into " + "数据库表名" + \
        " (" + columns + ") values (" + s_count[:-1] + ")"
    try:
        cursor.executemany(insert_sql, data_list)
        cursor.close()
        conn.close()
    except Exception as e:
        print("mysql插入失败")
        cursor.close()
        conn.close()


if __name__ == '__main__':
    conn = mysql_conn(config)
    query = "select * from database limit 1"
    res = get_mysql_data(conn, query)

    import pandas as pd
    df = pd.DataFrame()
    insert_data(conn, df)

Hbase

使用happybase库,以下代码测试分spark df 和 本地python格式数据写入以及简单读取hbase:

# -*- coding:UTF-8 -*-
import happybase
from pyspark.sql import SparkSession
# 设置日志输出
import logging
s_logger = logging.getLogger('py4j.java_gateway')
s_logger.setLevel(logging.ERROR)

# 设置spark连接方式,local模式可读取本地文件
spark = SparkSession.builder.master("local") \
    .appName("hbase_wr") \
    .getOrCreate()

# happybase操作类
class Happybase_ope:
# 初始化连接参数
    def __init__(self, host="host", timeout=None, table_prefix=None):
        self.connection = happybase.Connection(
            host=host, timeout=timeout, table_prefix=table_prefix)
 # 建表
    def createTable(self, tablename, families):
        self.connection.create_table(tablename, families)
# 连接表
    def table(self, tablename):
        return self.connection.table(tablename)
# 关闭连接
    def close(self):
        self.connection.close()

# spark df 批量写入
def WriteDF(num):
    hpbase = Happybase_ope()
    tbname = 'tbname'
    table = hpbase.table(tbname)
    # 分批写入
    bat = table.batch()
    bat.put(row=num[0][0], data={'info:data': num[0][1]})
    bat.send()
    hpbase.close()

# 写入一条数据
def WriteData(row,data):
    hpbase = Happybase_ope()
    tbname = 'tbname'
    table = hpbase.table(tbname)
    table.put(row=row, data=data)
    hpbase.close()

# 获取数据
def getData():
    hpbase = Happybase_ope()
    tbname = 'tbname'
    table = hpbase.table(tbname)
    # 指定行和列族获取数据
    res = table.row(row="info:data", columns="ent_name_hash_code1")
    return res


if __name__ == '__main__':
    result = spark.read.csv(
        'FilePath',
        header=True)
    
    result_rdd = result.rdd
    result_rdd.zipWithIndex().repartition(
        100).foreach(lambda zipArr: WriteDF(zipArr))

Solr

使用pysolr库连接solr获取数据

import pysolr as pl
solr = pl.Solr('solr查询页面地址',timeout=500000)
# rows为批量读取行数
def get_solr_data(solr,rows=200, timeout=100):
    # 游标
    current_cursor = "*"
    # 状态判断是否还有数据
    has_more = True
    results = []
    # 查询数据数量
    count = solr.search('*:*', **{'fq':'fq'}).hits
    while has_more:
        try:
            result =  solr.search('q', **{'fq':'fq','fl':'fl', "rows": rows,'sort': 'ID asc',
                                         "cursorMark": current_cursor},  timeout=timeout)
            if current_cursor == result.nextCursorMark:
                has_more = False
            else:
                current_cursor = result.nextCursorMark
            if result.docs:
                results.extend(result.docs)
        except Exception as e:
            print(e)
        finally:
            print(str(len(results)) + "/" + str(count))

    return results
data = get_solr_data(solr)

MongoDB

使用Pymongo连接mongo数据库进行增删改查

from pymongo import MongoClient

#创建数据库需要使用 MongoClient 对象,并且指定连接的 URL 地址和要创建的数据库名。
myclient = pymongo.MongoClient("mongodb://localhost:27017/")
#连接数据库
mydb = myclient["testdb"]
#连接表
mycol = mydb["testtabel"]
# 增加数据,mongo插入数据为字典格式,以"_id"为主键,如果插入数据中没有设置"_id",则会自己生成唯一id
mydict = {"name": "test", "sex": "男"}
mylists = [{"name": "test", "sex": "男"},
           {"name": "test1", "sex": "女"}]
# 插入一条数据
mycol.insert_one(mydict) 
# 插入多条数据
mycol.insert_many(mylist)
# 查询数据

# 获取第一条数据
mycol.find_one()

# 获取所有数据,find返回出来的数据是一个迭代器,需for循环使用或转为list等类型。
list(mycol.find())

# 条件查询,指定字典类型查询即可
query = {"name": "test"}
query1 = {"name": "test","sex": "男"}
mycol.find_one(query)
mycol.find_one(query1,{"name":1})  # {"name":1}表示只返回name列
# 修改数据

# 修改匹配到的第一条数据,update方法第一个参数为查询条件,第二个参数为修改字段。
myquery = { "name": "test" }
newvalues = { "$set": { "sex": "nan" } }
mycol.update_one(myquery, newvalues)
# 批量修改用many方法。
mycol.update_many(myquery, newvalues)
# 删除数据

# 条件删除,指定字典类型查询即可
query = {"name": "test"}
query1 = {"name": "test","sex": "男"}
# 删除匹配到的第一条数据
mycol.delete_one(query)
# 删除所有匹配到的数据
mycol.delete_many(query1)
批量更新
# 批量操作
# bulk_write(requests, ordered=True, bypass_document_validation=False, session=None)
# requests:一个包含写操作示例的列表(InsertOne, UpdateOne, UpdateMany, ReplaceOne, DeleteOne, or DeleteMany);
# ordered:表示是否顺序写入,设为True时其中的操作顺序执行,中间出错则后续操作都不会执行;设为False则所有的操作乱序执行,其中一个操作出错其余的操作不会受影响
from pymongo import ReplaceOne
# 一个批量更新方法
def upsert_mongo_data(data,batch_size = 200):
    bulk_list = []
    for da in data:
        doc = {"_id":id;
                "name":da["name"];
                "sex":da["sex"]
        }
        bulk_list.append(ReplaceOne({"_id":doc["_id"]},doc ,upsert = True))
        if len(bulk_list) < batch_size:
            continue
        mycol.bulk_write(bulk_list)
        bulk_list = []
    if bulk_list:
        mycol.bulk_write(bulk_list)
        
mylists = [{"name": "test", "sex": "男"},
           {"name": "test1", "sex": "女"}]

upsert_mongo_data(mylists)

SPARK

kudu

利用sparksession的read和write方法读取以及写入,需要设置用户和kudu表名,读取后数据格式为spark df。

from pyspark.sql import SparkSession

# 设置spark连接方式,local模式可读取本地文件
spark = SparkSession.builder.master("yarn") \
    .appName("xytest") \
    .getOrCreate()

# 读入kudu数据
data = spark.read.format("org.apache.kudu.spark.kudu")
        .option("kudu.table", "impala::test_tabel")
        .option("kudu.master", "master:7051")
        .option("kudu.operation.timeout.ms", "100000")
        .load()
        
# spark df 写入kudu表       
spark_df.write.format('org.apache.kudu.spark.kudu') \
    .option("kudu.table", "impala::test_tabel") \
    .option("kudu.master", "master:7051") \
    .mode('append') \
    .save()

hive

利用sparksession的sql和write方法读取以及写入,可直接读取平台上的hive数据库,读取后数据格式为spark df。

from pyspark.sql import SparkSession

# 设置spark连接方式,local模式可读取本地文件
spark = SparkSession.builder.master("yarn") \
    .appName("xytest") \
    .getOrCreate()

#hive读取,直接spark.sql
data = spark.sql('select * from db.tabel')

# spark df 写入hive表
spark_df.write.format("parquet").mode("overwrite").saveAsTable(hive_tabel)

hbase

有问题,后续解决补充。。。。。。

MongoDB

import os
from pyspark.sql import SparkSession
# set PYSPARK_PYTHON to python36
os.environ['PYSPARK_PYTHON'] = '/usr/bin/python36'
# load mongodb data # 格式是:"mongodb://127.0.0.1:database.collection"
input_uri = "mongodb://127.0.0.1:27017/spark.spark_test"
output_uri = "mongodb://127.0.0.1:27017/spark.spark_test"
# 创建spark,默认使用本地环境,或者"spark://master:7077"
spark = SparkSession.builder.master("local").appName("MyApp") \
        .config("spark.mongodb.input.uri",input_uri) \
        .config("spark.mongodb.output.uri", output_uri) \
        .config('spark.jars.packages', 'org.mongodb.spark:mongo-spark-connector_2.11:2.2.0') \
        .getOrCreate()
#collection:表名    pipeline:查询条件
df_1 = spark.read.format('com.mongodb.spark.sql.DefaultSource') \
        .option("collection", tabel) \
        .option("pipeline", query).load()

你可能感兴趣的:(Python & Spark 操作常见数据库整理)