1 前言

1-1 简介

工作中需要对所有的实体数据进行存储构建实体知识图谱,为基于知识图谱的问答提供数据基础。选择使用Neo4j作为数据库进行存储。以下是关于Neo4j的简介。

1-2 任务背景

将处理好的实体数据(共计1100万)写入图数据库中,并且提供查询接口,供下游(KBQA)进行查询。由于数据量比较大,所以需要批量更新、批量删除。

1-3 任务难点

任务难点有两个:

(1)因为数据处理的缘故,每个实体的属性不一致。比如“芈月”这一实体,其中存在{"name": "中文名", "value": "芈月"}, {"name": "别名", "value": "月儿、月公主、太后、公主、芈夫人、芈八子、月妹妹、王妹、母后、姐姐、小霸星、小老虎"}, {"name": "饰演", "value": "孙俪(成年)、柴蔚(少年)、李景儿(童年)、刘楚恬(童年)"}, {"name": "登场作品", "value": "芈月传"}等属性。而“布巴洛”则有{"name": "中文名", "value": "布巴洛"}, {"name": "运动项目", "value": "足球"}, {"name": "所属运动队", "value": "芭提雅联足球俱乐部"}, {"name": "场上位置", "value": "前锋"}等属性。如何根据不同的属性做出个性化的Node是面临的第一个难点。经过探索,解决此问题借助了字典的方式。

(2) 因为数据量庞大,如何将创建好的Node快速写入Neo4j中成为另一个难点。经过探索,解决此问题,采用了子图写入的方式。

1-3 数据来源

数据来源于百度百科的词条数据,对百科词条进行处理。部分样例如下所示:

{"lemmaTitle": "芈月", "lemmaDesc": "电视剧《芈月传》女主角", "lemmaSummary": {"value": "芈月,古装电视剧《芈月传》中的女主角。由演员孙俪饰演。芈月的历史原型为秦国的宣太后,她是中国历史上第一位太后。"}, "basicInfo": [{"name": "中文名", "value": "芈月"}, {"name": "别名", "value": "月儿、月公主、太后、公主、芈夫人、芈八子、月妹妹、王妹、母后、姐姐、小霸星、小老虎"}, {"name": "饰演", "value": "孙俪(成年)、柴蔚(少年)、李景儿(童年)、刘楚恬(童年)"}, {"name": "登场作品", "value": "芈月传"}, {"name": "所处时代", "value": "战国时期楚国→秦国"}, {"name": "民族族群", "value": "华夏族"}, {"name": "出生地", "value": "荆州"}, {"name": "出生日期", "value": "不详"}, {"name": "逝世日期", "value": "前265年"}, {"name": "主要成就", "value": "在秦国长期执政、杀义渠王、灭义渠国、囚死楚怀王"}, {"name": "心腹", "value": "葵姑、香儿、惠儿、穆辛"}, {"name": "谥号", "value": "宣"}, {"name": "父亲", "value": "羋(熊)商(楚威王)"}, {"name": "母亲", "value": "向氏"}, {"name": "丈夫", "value": "嬴驷"}, {"name": "弟弟", "value": "芈戎(同父同母)、魏冉(同母异父)、白起(义弟)"}, {"name": "初恋", "value": "黄歇"}, {"name": "情人", "value": "翟骊(义渠王)"}, {"name": "儿子", "value": "嬴稷(和嬴驷所生)、嬴芾(和翟骊所生)"}, {"name": "姐姐", "value": "芈姝(已决裂)、羋茵(天生不和)"}, {"name": "哥哥", "value": "羋(熊)槐(楚怀王、同父异母)"}, {"name": "侄子", "value": "羋(熊)横(楚顷襄王)"}, {"name": "好姐妹", "value": "樊长使、卫良人、唐夫人、孟赢、魏美人"}, {"name": "养母", "value": "莒姬"}, {"name": "仇人", "value": "魏琰、虢美人、孟昭氏、魏颐、甘茂、玳瑁、珍珠、珊瑚、靳尚、赢荡、芈姝、羋茵、楚威后、冯甲、羋(熊)槐、羋菁、郑袖、赢华"}, {"name": "师傅", "value": "屈原"}, {"name": "男宠", "value": "魏丑夫"}, {"name": "玄孙", "value": "秦始皇嬴政"}, {"name": "身份", "value": "楚国公主→芈八子→燕国质子→秦国太后(宣太后)"}, {"name": "好友", "value": "张仪、庸睿、樗里疾"}, {"name": "入秦宫身份", "value": "八子"}, {"name": "字号", "value": "宣"}, {"name": "朝代", "value": "战国时期"}, {"name": "国籍", "value": "楚国→秦国"}, {"name": "本名", "value": "芈月"}, {"name": "饰演者", "value": "孙俪"}, {"name": "性别", "value": "女"}], "order": 0, "category": "人物,虚拟人物,影视人物,文学角色,历史人物", "tags": "文化;出版物", "synonyms_lemmaTitle": ["芈月 电视剧《芈月传》女主角", "宣太后", "芈月"], "synonyms": "芈月\t电视剧《芈月传》女主角,宣太后,芈月"}
{"lemmaTitle": "布巴洛", "lemmaDesc": "塞尔维亚足球运动员", "lemmaSummary": {"value": "布巴洛是塞尔维亚足球运动员。"}, "basicInfo": [{"name": "中文名", "value": "布巴洛"}, {"name": "运动项目", "value": "足球"}, {"name": "所属运动队", "value": "芭提雅联足球俱乐部"}, {"name": "场上位置", "value": "前锋"}], "order": 0, "category": "人物", "tags": "人物", "synonyms_lemmaTitle": "布巴洛", "synonyms": "布巴洛"}

2  任务实现

2-1 安装Neo4j

安装版本为Community-4.4.8,进入到安装包目录下执行命令:

tar -xf neo4j-community-4.4.8-unix.tar.gz

安装完成后会生成如下目录:

conf目录下存放配置文件,可以根据自己服务器配置进行修改。

启动:

 进入bin目录执行./neo4j start

2-2 引入必要的库

import jsonlines
from tqdm import tqdm
import jsonlines
import pandas as pd

2-3 连接图数据库

2-3-1 连接图数据库

使用py2neo作为连接工具,完成对Neo4j的操作。引入必要的库函数,首先根据网址、用户名和密码建立连接。之后可以借助NodeMatcher方法生成查询。

#连接数据库
from py2neo import Graph, Node, Relationship,Subgraph,NodeMatcher
graph = Graph('http://xx.xx.xx.xxx:7474/browser/',auth=('neo4j', 'Neo4j'))
#创建查询
node_matcher = NodeMatcher(graph)
#数据库清空
#graph.delete_all() #DatabaseError: [Statement.ExecutionFailed] Java heap space

2-4 写入节点

2-4-1 创建Node

针对每条实体,将其中的key_value键值对进行整合,并生成字典。建立node,再使用node[key] = val,将每一条属性与属性值写入node中。

#读入数据
with open('/ssd/Spider/Neo4j_dataRelation1.jsonl',"r+")as reader :entity_lines = reader.readlines()
def get_Node(entity):test_dict = eval(entity)test_list = []for item_key in test_dict:if item_key == 'basicInfo':for basc_info in test_dict['basicInfo']:if basc_info['name'] and basc_info['value']:test_list.append((test_dict['lemmaTitle'],basc_info['name'],basc_info['value']))elif item_key == 'lemmaSummary':if test_dict['lemmaSummary']['value']:test_list.append((test_dict['lemmaTitle'],'lemmaSummary',test_dict['lemmaSummary']['value']))elif item_key=='synonyms_lemmaTitle' or item_key=='synonyms' :continueelif item_key=='category':if test_dict[item_key] !='':test_list.append((test_dict['lemmaTitle'],item_key,test_dict[item_key]))else:test_list.append((test_dict['lemmaTitle'],item_key,"None"))elif item_key=='tags':if test_dict[item_key] !='':test_list.append((test_dict['lemmaTitle'],item_key,test_dict[item_key]))else:test_list.append((test_dict['lemmaTitle'],item_key,"None"))elif item_key =='star_relations':for item in test_dict[item_key]:if item['name'] and item['value']:test_list.append((test_dict['lemmaTitle'],item['name'],item['value']+"_"+item['lemmaId']))elif item_key == 'lemma_relations':for item in test_dict[item_key]:if item['name'] and item['value']:test_list.append((test_dict['lemmaTitle'],item['name'],item['value']+"_"+item['lemmaId']))elif item_key == 'Relation':continueelse:test_list.append((test_dict['lemmaTitle'],item_key,test_dict[item_key]))#建立字典entity_dict = {}for item in test_list:#entity_dict.setdefault(item[1],[]).append(item[2])entity_dict[item[1]] = item[2]label = 'Common_test'entity_name = entity_dict['lemmaTitle']node = Node(label,name=entity_name)#graph.create(node)for key, val in entity_dict.items():node[key] = val#graph.push(node)return node

2-4-2 建立子图

在写入时,选择了开销最小并且最为稳妥的子图写入方式, subgraph = Subgraph(node_ls, relation_ls),需要对Subgraph()传入两个参数,node_ls表示节点列表,relation_ls表示关系列表,如果只是想写入节点,那就将relation_ls用[]代替。

def write_neo4j(node_ls):#构建子图subgraph = Subgraph(node_ls, [])#构建事务Transaction = graph.begin() Transaction.create(subgraph)#提交graph.commit(Transaction)

2-4-3 子图写入

使用子图的方式写入节点,本次写入中以1万为一个批次写入,写入之后将节点列表清空。 写入100万数据用时9分钟。

Node_list = []
for entity in tqdm(entity_lines[:1000000]):node = get_Node(entity)Node_list.append(node)if len(Node_list) == 10000:write_neo4j(Node_list)Node_list = []

2-5 创建索引

说明:为label是Common_test的实体的lemmaTitle创建索引,

#index_command = 'create index on:Common(lemmaTitle)'
index_command = 'create index on:Common_test(lemmaTitle)'
result = graph.run(index_command)

2-6 查询

说明:创建索引后,在100万节点的库中查询单实体,查询一条用时59ms

#查询
search_result = graph.nodes.match("Common_test").where(lemmaTitle='中国').all()  # [0].items()
#search_result
#search_result[0].items()

3 后记

在处理数据时,每条实体数据的存储形式都是以key:value的形式存储,每条实体数据都有不同的key和value。所以做数据导入时,要根据每一条实体数据做’个性化处理‘。将数据中的属性写到列表中,然后再通过key、value的方式push到节点中。初次写入时,每个实体都单独处理,首先create node,然后再形成字典,进行push,这样的方法效率非常慢,因为每次创建节点再进行push都需要进行查库,并且随着库中数据量大增多,导致写入速度越来越慢。后面尝试够使用Load CSV 的方式写入,但是由于实体数量庞大,每个实体会有不同的属性,从而导致csv的维度有60W维,并且csv的维度及其稀疏,写入都需要占用巨大的内存,后遂放弃。最后了解到使用子图的方式可以写入,先将node存放到列表中,当然也可以存放关系形成subgraph = Subgraph(node_ls, relation_ls)的形式,如果relation_ls为空则写成ubgraph = Subgraph(node_ls, [])。随后可以控制节点列表的长度,文中在写入时设置的大小为1万,当列表的长度到达1万之后,便一次性提交。将一万多节点批次写入。这样既满足了节点数据个性化的要求,又实现了批量写入。

写入数据后,便是创建索引,因为每个实体节点在写入时,为其贴上了标签(label),本次写入时的label设置为Common_test,所以在创建索引时,需要用到标签信息。之后就可以为实体的具体属性创建索引。创建索引后查询速度提升80%。

Neo4j图数据库 批量写入与查询相关推荐

  1. Task 5 Cypher 介绍及Neo4j 图数据库查询

    Datawhale 知识图谱组队学习 Task 5 Neo4j 图数据库查询 一. Neo4介绍 二. Neo4j 介绍 3.1 Cypher 介绍 3.2 Neo4j 图数据库 查询 四. 基于知识 ...

  2. neo4j图数据库:结构化数据流水线、非结构化数据流水线

    日萌社 人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新) 智能对话系统:Unit对话API 在线聊天的总体架构与工具介绍 ...

  3. Pyhton操作Neo4j图数据库实践(南北朝隋唐历史北朝主要人物知识图谱)

    独孤信"第一岳父"之称很形象,他有三个女儿做了三个朝代皇后,以及杨坚.杨广.李渊等人关系.本文试着使用图数据库(neo4j)表达这段南北朝隋唐历史北朝主要人物知识图谱. 1. Ne ...

  4. neo4j︱图数据库基本概念、操作罗列与整理(一)

    图数据库常规的有:neo4j(支持超多语言).JanusGraph/Titan(分布式).Orientdb,google也开源了图数据库Cayley(Go语言构成).PostgreSQL存储RDF格式 ...

  5. neo4j图数据库基本概念

    简介:本文以电影关系图为例,解释neo4j图数据库中的基本概念 电影关系图 下图中的圆圈表示三个节点(node),每个节点都有表示类别的标签(label)和属性(properties),如:name. ...

  6. neo4j 图数据库初步调研 三元组、属性图、图模型、超图、RDF-f

    相关文章 neo4j 图数据库初步调研 图数据库与关系型数据库差异 demo项目(python+vue) 本文目录 相关文章 一.技术关键字 二.前言 1.什么是图 2.反规范化 三.RDF(资源描述 ...

  7. neo4j 图数据库初步调研 图数据库与关系型数据库差异-f

    相关文章 neo4j 图数据库初步调研 三元组.属性图.图模型.超图.RDF demo项目(python+vue) 本文目录 相关文章 一.技术关键字 二.前言 三.图数据库与传统数据库 1.反规范化 ...

  8. Neo4j图数据库从入门到精通

    add by zhj: 转载时,目录没整理好,还会跳转到原文 其实RDB也可以存储多对多的关系,使用的是中间表,GDB使用的是边,RDB中的实体存储在数据表,而GDB存储在节点.两者使用的底层技术不同 ...

  9. 聊聊Neo4j图数据库的那些明显优势

    摘要: Neo4j是一个NoSQL的图数据库管理系统,像其他NoSQL数据库一样具有高效的查询性能.同时,Neo4j还具有完全事务管理特性,完全支持ACID事务管理.Neo4j与其他数据库相比,具有哪 ...

最新文章

  1. Netty初步之hello world
  2. 全国计算机等级考试题库二级C操作题100套(第04套)
  3. 计算机二级晓云是企业人力,全国计算机二级Ms-Office精选真题试卷
  4. 【1】mongoDB 的安装及启动
  5. Maven的核心笔记(3)常用命令、坐标和仓库
  6. 【系统架构】如何逐步去构建一个大型网站系统
  7. 正点原子STM32f4系列其他串口通信失败问题解决
  8. java自学网视频教程,系列教学
  9. steamcommunity本地反代443端口/80端口被占用解决办法
  10. php一键集成环境安装包,APMXN集成环境一键安装包(php环境一键安装包)V1.0.2 最新版...
  11. python word转pdf linux_在Linux系统中把Pdf转化成word文档的软件
  12. Node.js局域网文件共享
  13. 关于计算机体系结构-北桥和南桥
  14. Tolerance Analysis 尺寸公差分析
  15. 基于OpenCV实现简单人脸面具、眼镜、胡须、鼻子特效(详细步骤 + 源码)
  16. spring cloud 实现服务不间断
  17. HTML学习总结 基础篇 图像标签imag的使用及其属性
  18. 浅析web应用防火墙的反向代理部署
  19. 复旦大学教授肖仰华:ChatGPT 浪潮下,面向大模型如何做数据治理?
  20. ASP.NET MVC5 实现基于Quartz.NET任务调度

热门文章

  1. Windows Server 2008 R2使用WDS服务实现批量安装操作系统演示
  2. post模拟传数据的几种方法
  3. linux下查看服务器的cpu、内存大小、硬盘大小
  4. 直播平台软件开发中选择点播播放器哪家强?
  5. GEE行政区加载,高程坡度计算和裁剪
  6. 在线支付——如何防止订单重复支付?
  7. i5四核八线程怎么样_四核八线程和六核六线程cpu相比哪个好?
  8. [2]工作流框架:支持MySQL的Flowable安装
  9. 微信小程序(WeUI框架)
  10. 利用vue实现树表格分页