返回顶部
热门问答 更多热门问答
技术文章 更多技术文章

使用Neo4j构建豆瓣电影知识图谱

[复制链接]
链载Ai 显示全部楼层 发表于 8 小时前 |阅读模式 打印 上一主题 下一主题

知识图谱在大语言模型兴起之前,一度被作为最有可能实现AGI的技术之一,只是大语言模型火了之后,这项技术慢慢没那么受关注了,但这项技术本身毋庸置疑还是可以解决一些问题的。本文使用一份开源的豆瓣电影数据,使用当前最流行的图数据库Neo4j,构建一个电影知识图谱,并在上面做一些简单的分析,诸如“演员最多的电影”、“参演电影超过10部的演员及其参演的电影”、“黄渤和莱昂纳多·迪卡普里奥的最短距离”等。

本文清洗好的以便于导入Neo4j的数据已经在Github开源,地址为:https://github.com/Steven-Luo/neo4j-douban-movies

1 环境说明

  • Neo4j数据库版本:5.20.0 Enterprise,企业版个人可以免费使用

2 数据

原始数据来源:http://data.openkg.cn/dataset/douban-movie-kg原始数据大家可以访问上面的链接,或者到Github仓库中,获取加工好的可以直接导入Neo4j的数据

3 数据预处理

原始数据每条记录只有一个电影记录,并没有抽象出节点和关系,通过数据预处理,对节点和关系进行抽象和重组,消除数据冗余,便于后续分析。具体而言,有以下节点类型:

  • 电影——Movie

  • 人——Person

  • 语言——Language

  • 发行地区——District

  • 电影类型——Category

有以下关系类型:

  • 参演——ACTED_IN

  • 导演——DIRECTED_IN

  • 编剧——COMPOSED

  • 拥有类型——CATEGORIZED_TO

  • 拥有主要语言——HAS_MAIN_LANGUAGE

  • 发行于——RELEASED_IN

schema或者所谓的本体如下:







os.makedirs(,exist_ok=)

data=json.load(())



persons=[]
categories=[]
languages=[]
movies=[]
districts=[]


acted_in=[]
categorized_to=[]
directed=[]
composed=[]
released_in=[]
has_main_language=[]

itemdata:
key(,,,,):
item[key]:
item[key]=[]

persons.extend(item[])
persons.extend(item[])
persons.extend(item[])

languages.extend(item[])
districts.extend(item[])
categories.extend(item[])

movies.append({
:item[],
:item[],
:item[],
:item[],
:item[],
item[])item[],
item[])item[],
:item[]
})

directoritem[]:
directed.append({
:item[],
:director
})

composeritem[]:
composed.append({
:item[],
:composer
})

actoritem[]:
acted_in.append({
:item[],
:actor
})

categoryitem[]:
categorized_to.append({
:item[],
:category
})

regionitem[]:
released_in.append({
:item[],
:region
})

languageitem[]:
has_main_language.append({
:item[],
:language
})



item[
(,persons),
(,categories),
(,languages),
(,movies),
(,districts)
]:
item[]==:
pd.DataFrame(item[]).to_csv(os.path.join(,item[]+),index=)
:
pd.DataFrame((item[]),columns=[]).to_csv(os.path.join(,item[]+),index=)


rel[
(,acted_in),
(,categorized_to),
(,directed),
(,composed),
(,released_in),
(,has_main_language),
]:
pd.DataFrame(rel[]).to_csv(os.path.join(,rel[].upper()+),index=)

4 导入数据

4.1 准备工作

4.1.1 修改配置

准备工作,首先要修改配置,在下图Settings...中,

注释掉如下的语句,这样可以允许导入数据时,从任意路径导入:

server.directories.import=import

4.1.2 安装插件

另外,需要安装APOC插件

4.1.3 创建数据库

这一步可选,在Neo4j界面上创建即可

4.2 开始导入

后续所有导入操作,在Neo4j Browser中进行

4.2.1 导入节点信息

4.2.1.1 导入Movie

旧版的Cypher语句

:auto

(:Movie{
id:line[id],
title:line[title],
cover:line[cover],
length:toInteger(line[length]),
rate:toFloat(line[rate]),
showtime:toInteger(line[showtime]),
url:line[url],
othername:line[othername]
})

Neo4j 4.0及以上版本不再支持 USING PERIODIC COMMIT,需要使用 CALL { ... } IN TRANSACTIONS 进行替换。上面只是旧版本的示例,后续不再包含旧版本Cypher语句。

注意:路径中不要包含中文,否则会报Bad escape (Transactions committed: 0)

{
line
(:Movie{
id:line[id],
title:line[title],
cover:line[cover],
length:toInteger(line[length]),
rate:toFloat(line[rate]),
showtime:toInteger(line[showtime]),
url:line[url],
othername:line[othername]
})
}TRANSACTIONS

4.2.1.2 导入Person

{
line
(erson{
name:line[name]
})
}TRANSACTIONS

4.2.1.3 导入District

{
line
(istrict{
name:line[name]
})
}TRANSACTIONS

4.2.1.4 导入Language

{
line
(anguage{
name:line[name]
})
}TRANSACTIONS

4.2.1.5 导入Cateogory

:autoLOADCSVWITHHEADERSFROMASline
CALL{
WITHline
CREATE(:Category{
name:line[]
})
}INTRANSACTIONS

4.2.2 建立索引

4.2.2.1 对节点建立索引

这个地方Cypher语句也跟Neo4j版本有关,旧版本:

indexon:Movie(title);

新版本:

INDEXmovie_title_indexFOR(m:Movie)ON(m.title);
INDEXperson_name_indexFOR(person)ON(p.name);
INDEXcategory_name_indexFOR(c:Category)ON(c.name);
INDEXlanguage_name_indexFOR(language)ON(l.name);
INDEXdistrict_name_indexFOR(district)ON(d.name);

4.2.2.2 查看索引状态

:schema

4.2.3 导入关系

4.2.3.1 导入ACTED_IN关系

{
line
(serson{name:line[actor]}),(e:Movie{id:line[movie_id]})
(s)-[:ACTED_IN]->(e)
}TRANSACTIONS

4.2.3.2 导入CATEGORIZED_TO关系

{
line
(s:Movie{id:line[movie_id]}),(e:Category{name:line[category]})
(s)-[:CATEGORIZED_TO]->(e)
}TRANSACTIONS

4.2.3.3 导入DIRECTED关系

{
line
(serson{name:line[director]}),(e:Movie{id:line[movie_id]})
(s)-[IRECTED]->(e)
}TRANSACTIONS

4.2.3.4 导入COMPOSED关系

{
line
(serson{name:line[composer]}),(e:Movie{id:line[movie_id]})
(s)-[:COMPOSED]->(e)
}TRANSACTIONS

4.2.3.5 导入RELEASED_IN关系

{
line
(s:Movie{id:line[movie_id]}),(eistrict{name:line[region]})
(s)-[:RELEASED_IN]->(e)
}TRANSACTIONS

4.2.3.6 导入HAS_MAIN_LANGUAGE关系

{
line
(s:Movie{id:line[movie_id]}),(eanguage{name:line[language]})
(s)-[:HAS_MAIN_LANGUAGE]->(e)
}TRANSACTIONS

4.2.4 查看schema

db.schema.visualization

或者

CALLapoc.meta.graph



4.3 分析

4.3.1 演员数量最多的10部电影

p=(erson)-[r:ACTED_IN]->(m:Movie)
m,count(p)cnt
m.title,cntcnt

4.3.2 参演电影最多的10个演员

path=(person)-[:ACTED_IN]-()
p,count(path)cnt
p.name,cntcnt

4.3.3 参演电影超过10部的演员,获取演员、电影

(person)-[:ACTED_IN]->(m:Movie)
p,count(m)rels,collect(m)movies
rels>
p,movies,rels
rels

4.3.4 导演电影最多的导演

path=(person)-[IRECTED]-()
p,count(path)cnt
p.name,cntcnt

4.3.5 “莱昂纳多·迪卡普里奥”和“黄渤”的最短路径,限定只能是ACTED_IN关系,同时限定必须是1至8度关系

p=shortestPath((erson{name:})-[:ACTED_IN*..]-(:Person{name:}))
p

4.3.6 “莱昂纳多·迪卡普里奥”和“黄渤”的最短路径,限定只能是ACTED_IN或DIRECTED关系,同时限定必须是1至8度关系,获取他们的最短距离长度

p=shortestPath((:Person{name:})-[r:ACTED_IN|DIRECTED*..]-(:Person{name:}))
size(r)


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

链载AI是专业的生成式人工智能教程平台。提供Stable Diffusion、Midjourney AI绘画教程,Suno AI音乐生成指南,以及Runway、Pika等AI视频制作与动画生成实战案例。从提示词编写到参数调整,手把手助您从入门到精通。
  • 官方手机版

  • 微信公众号

  • 商务合作

  • Powered by Discuz! X3.5 | Copyright © 2025-2025. | 链载Ai
  • 桂ICP备2024021734号 | 营业执照 | |广西笔趣文化传媒有限公司|| QQ