📅  最后修改于: 2023-12-03 15:12:52.363000             🧑  作者: Mango
本项目基于图数据库实现了一个推荐系统,主要功能是根据用户的兴趣爱好和历史行为,推荐给用户相似的内容。推荐系统是现代互联网业务中的核心应用之一,可以用于电商平台、社交网络、影视娱乐等领域。
在传统的关系型数据库中,推荐系统主要是通过建立用户-物品的关系矩阵,运用协同过滤、矩阵分解等算法实现的。但是,经典的推荐算法往往只考虑了单一的因素,比如用户和物品之间的相似度,而忽略了更复杂的因素和关系,比如用户群体和物品类别等。这些复杂因素和关系无法用简单的结构来表达和存储,因此图数据库应运而生。
本项目所采用的技术栈如下:
该推荐系统主要由四个部分组成:
本项目使用了图数据库Neo4j来存储数据。与传统的关系型数据库不同,Neo4j采用了图论的思想,将数据存储为节点和边的形式。本项目将用户、物品、标签等信息存储在图数据库中,用节点表示不同的实体,用边表示它们之间的关系。
数据获取模块主要负责从MySQL数据库中获取用户和物品信息,根据不同的规则构建出图数据库中的节点和边,更新图数据库中的数据。
推荐算法模块采用了基于图的推荐算法,主要包括以下几个步骤:
推荐服务模块向前端提供推荐数据,用户通过前端页面进行交互,将推荐结果展示出来。
以下是部分代码片段,完整代码请见https://github.com/xxx/xxx。
# 数据库连接
from neo4j import GraphDatabase
driver = GraphDatabase.driver("bolt://localhost:7687", auth=("neo4j", "password"))
# 推荐算法
def recommend(userId):
session = driver.session()
# 找出用户感兴趣的物品类别
interestTags = session.run('MATCH (user:User)-[:LIKE]->(tag:Tag) '
'WHERE user.id=$userId '
'RETURN tag.name AS tagName', userId=userId)
recommendItems = []
for interestTag in interestTags:
tagName = interestTag['tagName']
# 找出所有包含该物品类别的物品
items = session.run('MATCH (item:Item)-[:HAS]->(tag:Tag) '
'WHERE tag.name=$tagName '
'RETURN item', tagName=tagName)
for item in items:
itemId = item['item']['id']
# 找出用户和该物品之间的联系程度
relation = session.run('MATCH (user:User)-[r:SIMILARITY]-(item:Item) '
'WHERE user.id=$userId AND item.id=$itemId '
'RETURN r.similarity AS similarity', userId=userId, itemId=itemId).single()
if relation is None:
# 如果用户和该物品没有联系,就建立一条联系
session.run('MATCH (user:User), (item:Item) '
'WHERE user.id=$userId AND item.id=$itemId '
'CREATE (user)-[:SIMILARITY {similarity:1.0}]->(item)', userId=userId, itemId=itemId)
elif relation['similarity'] < 1.0:
# 如果用户和该物品的联系程度小于1,就更新联系
session.run('MATCH (user:User)-[r:SIMILARITY]-(item:Item) '
'WHERE user.id=$userId AND item.id=$itemId '
'SET r.similarity=$similarity', userId=userId, itemId=itemId, similarity=relation['similarity']+0.1)
# 将推荐物品和用户之间建立边
session.run('MATCH (user:User), (item:Item) '
'WHERE user.id=$userId AND item.id=$itemId '
'CREATE (user)-[:RECOMMEND]->(item)', userId=userId, itemId=itemId)
if itemId not in recommendItems:
# 如果该物品还没有被推荐过,就加入待推荐列表
recommendItems.append(itemId)
# 找出待推荐物品的详细信息
result = []
for itemId in recommendItems:
item = session.run('MATCH (item:Item) '
'WHERE item.id=$itemId '
'RETURN item', itemId=itemId).single()
result.append(item['item'])
session.close()
return result
<!-- 前端页面 -->
<div id="recommend-list">
<ul>
<li v-for="item in recommendItems">
<div>{{ item.name }}</div>
<div>{{ item.price }}</div>
<div>{{ item.description }}</div>
</li>
</ul>
</div>
<script>
// 调用推荐服务
$.ajax({
url: '/recommend?userId=1',
type: 'GET',
success: function(data) {
app.recommendItems = data;
}
});
</script>