说明
大多数推荐系统学习,要么讲解算法,要么讲解理论。
这里,我们结合python和pgsql数据库,从0开始搭建一个电影推荐系统。
数据库操作(pgsql)
创建一个数据库用户,用于管理推荐系统相关数据库对象
create user hrjlk_recomm with password '123456';
创建表空间,用于存储推荐系统相关的数据
create tablespace ts_recomm_data owner hrjlk_recomm location '/Users/../data_ts/ts_recomm_data';
创建电影推荐的数据库
create database db_movies owner hrjlk_recomm tablespace ts_recomm_data encoding utf8;
退出当前用户
\q
切换推荐系统的数据库用户重新登录
psql -h localhost -U hrjlk_recomm -d db_movies
创建表,保存用户对电影的评分数据
create table user_move_ratings (
ratingId serial not null primary key
,userId int not null
,moveId int not null
,ratingVal decimal(2,1) not null
,created_at varchar(16) not null
);
comment on table user_move_ratings is '用户电影评分记录';
comment on column user_move_ratings.ratingId is '评分记录ID';
comment on column user_move_ratings.userId is '用户ID';
comment on column user_move_ratings.moveId is '电影ID';
comment on column user_move_ratings.ratingVal is '用户对电影的评分';
comment on column user_move_ratings.created_at is '数据创建时间';
导入数据,我用的是Posticon工具,总计20000263行。
数据文件获取,关注公众号“自然语言酷”,后台发送表名,客服每天统一回复网盘地址
python项目
环境(python3.6以上)
需要各位自行安装py-postgresql
pip install py-postgresql
配置
创建目录hrjlk-recomm,并建立下一级目录 src
src
下新建目录conf
conf
目录下,新建conf.ini
文件
用于保存相关配置
[HRJLK-DB-MOVIE]
USER = hrjlk_recomm
PASSWORD = 123456
HOST = 127.0.0.1
PORT = 5432
DATABASE = db_movies
conf
目录下,新建sql.ini
文件
sql语句的配置文件
[RATING]
GET_USER_MOVIE_RATING = select ratingVal from user_movie_ratings where userId={user_id} and moveId={move_id};
Utils
src下,新建目录utils
新建python文件,dbHandle.py,数据库操作的工具类
# -*- coding:utf-8 -*-
import os
import postgresql.driver as pg_driver
import configparser
class DBHandle:
# 配置文件的路径
__configPath = '../../conf/conf.ini'
# 声明一个配置文件Reader
confReader = None
def __init__(self,dbName):
if os.path.exists(self.__configPath):
confReader = configparser.ConfigParser()
confReader.read(self.__configPath)
else:
raise IOError("config file path is:'" + self.__configPath + "'not found")
# 初始化数据库连接
self.dbConn = pg_driver.connect(user=confReader.get(dbName, 'USER')
, password=confReader.get(dbName, 'PASSWORD')
, host=confReader.get(dbName, 'HOST')
, port=confReader.get(dbName, 'PORT')
, database=confReader.get(dbName, 'DATABASE')
)
# 执行查询,只取第一行,实现查询一行的功能
def executeQueryFirst(self, sqlText):
firstQuery = self.dbConn.prepare(sqlText)
return firstQuery.first()
# 执行查询
def executeQuery(self,sqlText):
queryPrepare = self.dbConn.prepare(sqlText)
return queryPrepare
# 执行插入数据,列表形式批量插入
def executeInsertLoad(self, sqlText, listLines):
insertQuery = self.dbConn.prepare(sqlText)
insertReturn = insertQuery.load_rows(listLines)
# 将查询结果插入目标表
def executeInsertSql(self,sqlText):
insertResult = self.dbConn.execute(sqlText)
# Truncate table
def executeTruncate(self,tableName):
_sqlTruncae = 'truncate table %s' % (tableName)
self.dbConn.execute(_sqlTruncae)
# 删除当日数据
def executeDelDateData(self,tableName,dataDate):
_sqlDel = "delete from %s where data_date = '%s'" % (tableName,dataDate)
self.dbConn.execute(_sqlDel)
# 关闭数据库连接
def closeDBConnection(self):
if self.dbConn:
self.dbConn.close()
创建python文件,DataUtil.py,配置类
class DataConfig:
sqlFilePath = '../../conf/sqls.ini'
dbNameRecomm = 'HRJLK-DB-MOVIE'
创建python文件,fileUtil.py,文件操作的工具类
# -*- coding:utf-8 -*-
import configparser
import os
class confReader:
"""
读取配置文件,适用于单次读取
"""
def __init__():
pass
'''
读取ini配置文件中值的工具方法
'''
@staticmethod
def readConfvalue(confFilePath,sectionName,keyName):
if os.path.exists(confFilePath):
confReader = configparser.ConfigParser()
confReader.read(confFilePath)
confVal = confReader.get(sectionName, keyName)
return confVal
else:
raise IOError("config file path is:'" + confFilePath + "'not found")
执行文件
src
下新建目录executer
,并新建python文件test.py
这里完成第一步,也是最基本的功能,根据用户ID和电影ID,查出用户对该电影的评分
# -*- coding:utf-8 -*-
import sys
sys.path.append('../utils')
from dbHandle import DBHandle
from dataUtil import DataConfig
from fileUtil import ConfReader
# 从配置文件中读取sql内容
__sqlModelName = 'RATING'
sqlContent = ConfReader.readConfvalue(DataConfig.sqlFilePath,__sqlModelName,'GET_USER_MOVIE_RATING')
# 创建数据库连接
dbConn = DBHandle(DataConfig.dbNameRecomm)
dbResultUserMoveRating = dbConn.executeQuery(sqlContent.format(user_id = sys.argv[1],move_id = sys.argv[2]))
print(dbResultUserMoveRating.first())
# 关闭连接
dbConn.closeDBConnection()
在命令行执行
python test.py 1 2
关注公众号“自然语言酷”,每周更新,大数据架构师进步之路。