简介
完整项目资源链接:https://download.csdn.net/download/m0_46573428/87796553
项目详细信息请看:毕业设计:Vue3+FastApi+Python+Neo4j实现主题知识图谱网页应用——前言_人工智能技术小白修炼手册的博客-CSDN博客
数据处理模块的数据上传功能。
主要代码
前端
Html
-
在template标签内部定义了一个div元素(id为“main”),并将其分为左侧和右侧两个部分,每个部分包含一个具有样式属性和事件绑定的滚动列表。
-
同样在这个div元素内部定义了两个上传按钮,点击按钮会触发上传事件。
-
在li标签内部渲染了节点列表和关系列表,并为它们提供了丢弃节点和关系的事件。
<template>
<div>
<div id="main">
<h1 style="margin-right: 50px">实体</h1>
<h1>关系</h1>
<div class="left">
<div style="height: 100%; overflow: scroll">
<ul class="ShiTi">
<li
:class="{ _dis: !item.Choose }"
@click="discardNode(index)"
v-for="(item, index) in newNode"
:key="index"
>
<p>{{ item.名称 }}</p>
<p v-for="(iitem, ikeys, iindex) in item" :key="iindex">
<span>{{ ikeys }}:</span>
<span>{{ iitem }}</span>
</p>
</li>
</ul>
</div>
</div>
<div class="right">
<div style="height: 100%; overflow: scroll">
<ul class="GuanXi">
<li
:class="{ _dis: !item.Choose }"
@click="discardRel(index)"
v-for="(item, index) in newRel"
:key="index"
>
<p>{{ item.start }}</p>
<p>{{ item.rel_name }}</p>
<p>{{ item.end }}</p>
</li>
</ul>
</div>
</div>
<button @click="confirm_node()" style="margin-right: 50px">
上 传 实 体
</button>
<button @click="confirm_rel()">上 传 关 系</button>
</div>
</div>
</template>
Script
-
定义了一个名为DataUpload的Vue.js属性包括newNode(新节点数组),newRel(新关系数组)和id(数据集的唯一标识符)。
-
组件的methods属性包括discardNode、discardRel、loadItems、confirm_node和confirm_rel等方法。其中,discardNode和discardRel方法被用于标记(选中或取消选中)节点和关系,loadItems方法用于加载数据并更新newNode和newRel数组,而confirm_node和confirm_rel用于确认上传融合的节点和关系,分别通过axios库进行POST请求。
1. discardNode方法
该方法用于丢弃一个节点,在实体列表中单击节点时会触发该事件。该方法将newNode数组中的相应元素Choose属性的值取反来标记节点是否被选中。Choose用来存储节点是否被选中。
2. discardRel方法
该方法用于丢弃一个关系,在关系列表中单击关系时会触发该事件。该方法将newRel数组中的相应元素Choose属性的值取反来标记关系是否被选中。
3. loadItems方法
该方法通过axios库进行GET请求以加载新节点和关系,该请求获取id作为参数,并返回包含节点和关系数组的JSON对象。在获取数据之后,该方法将响应结果中的新节点和关系信息存储在组件的newNode和newRel数据属性中,以便稍后使用。
4. confirm_node方法
该方法用于确认上传融合的节点。首先它在dataInput_node数组中记录所选的所有节点(遍历newNode的元素,如果被选中就添加到数组),然后使用axios库进行POST请求来将这些节点上传到服务器上。请求参数node是包含节点信息的JSON字符串,当请求成功时,会通过res.data.msg属性提示上传成功。
5. confirm_rel方法
该方法用于确认上传融合的关系。与confirm_node方法类似,该方法在dataInput_rel数组中记录所选的所有关系,然后使用axios库进行POST请求来将这些关系上传到服务器上。请求参数rel是包含关系信息的JSON字符串,当请求成功时,会通过res.data.msg属性提示上传成功。
这些方法实现了数据的上传和融合。通过在Vue.js中区分实体和关系,让用户可以选择上传自己需要的数据部分。通过使用axios库进行GET和POST请求,可以将已选节点和关系传送到服务器进行后续处理。
<script>
export default {
name: "DataUpload",
props: {},
data() {
return {
newNode: [],
newRel: [],
id: 0,
};
},
methods: {
discardNode: function (index) {
this.newNode[index].Choose = !this.newNode[index].Choose;
},
discardRel: function (index) {
this.newRel[index].Choose = !this.newRel[index].Choose;
},
// 数据融合:加载新节点
loadItems: function () {
this.axios
.get("http://localhost:8000/NewItem?database_id=" + this.id)
.then((res) => {
if (res.data == "数据为空") {
alert("数据集为空");
}
this.newNode = res.data[0];
this.newRel = res.data[1];
})
.catch((error) => {
alert("NewNode failed!");
});
},
// 数据融合:确认融合实体
confirm_node: function () {
var dataInput_node = [];
for (var i = 0; i < this.newNode.length; i++) {
if (this.newNode[i].Choose == true) {
this.newNode[i].Choose = "true";
dataInput_node.push(this.newNode[i]);
}
};
console.log(dataInput_node);
this.axios
.post(
"http://localhost:8000/Nodes2Graph?dataInput_node=" +
JSON.stringify(dataInput_node)
)
.then((res) => {
alert(res.data.msg);
})
.catch((error) => {
alert("Nodes2Graph failed!");
});
for (var i = 0; i < this.newNode.length; i++) {
if (this.newNode[i].Choose == "true") {
this.newNode[i].Choose = true;
}
}
},
// 数据融合:确认融合关系
confirm_rel: function () {
console.log(this.newRel);
var dataInput_rel = [];
for (let item in this.newRel) {
if (this.newRel[item].Choose == true) {
dataInput_rel.push(this.newRel[item]);
}
};
console.log(dataInput_rel);
this.axios
.post(
"http://localhost:8000/Rels2Graph?dataInput_rel=" +
JSON.stringify(dataInput_rel)
)
.then((res) => {
alert(res.data.msg);
})
.catch((error) => {
console.log(error);
alert("Rel2Graph failed!");
});
},
},
mounted() {
this.id = this.$route.params.id;
this.loadItems();
},
};
</script>
Css
<style scoped>
* {
color: #666;
}
#main {
width: 90%;
margin-left: 50px;
padding-top: 40px;
}
#main > div {
height: 320px;
border: #ccc solid 1px;
width: 41%;
float: left;
border-radius: 15px;
padding: 10px 0px 10px 20px;
}
h1 {
float: left;
width: 44%;
text-align: center;
font-size: 20px;
margin-bottom: 20px;
color: #486e53;
}
.left {
margin-right: 50px;
}
button {
float: left;
border: none;
background: rgb(107, 146, 77);
color: white;
padding: 8px 10px;
font-weight: bold;
border-radius: 15px;
margin-top: 30px;
width: 44.5%;
cursor: pointer;
}
.ShiTi > li {
width: 250px;
}
._dis {
background: #bbb;
}
.ShiTi > li > p:first-child {
font-weight: bold;
margin-top: 10px;
color: #486e53;
}
.ShiTi > li > p > span:first-child {
font-size: 14px;
font-weight: 400;
margin-top: 10px;
}
.ShiTi > li > p > span:nth-child(2) {
font-size: 14px;
}
.GuanXi > li {
margin-top: 10px;
width: 250px;
}
.GuanXi > li > p:nth-child(2) {
color: #486e53;
font-weight: bold;
}
</style>
后端
NewItem(database_id)
函数NewItem(database_id)用于读取特定格式数据集中的实体、关系信息并将它们存储在列表中。
具体来说,该函数读取数据集(通过参数database_指定),并遍历其中的每个文件。对于每个文件,函数将从打开的文件流中读取数据行,并将其转换为字典对象tmp,其中tmp['nodes']包含了实体信息,tmp['rels']包含关系信息。
如果实体列表非空,则遍历实体集合并将其元素添加到new_node列表中。对于每一个实体元素,函数会自动为其添加Choose属性并将其设置为True,用于在后续处理中标记该节点是否被选中。同样,如果rel列表非空,则遍历关系集并将每个关系添加到new_rel列表中,也会添加Choose属性并设置为True。
最后,函数将new_node和new_rel数组组合成一个新的列表new_item,并返回给调用者。如果获得的new_item列表为空,则函数会返回字符串“数据为空”。
# 输出数据集中的实体与属性与关系
def NewItem(database_id):
"""
作用:输出数据集中的实体与属性与关系
输入:数据集id
输出:实体、关系信息的列表
"""
files_list = DataPath(database_id)
new_item = []
new_node = []
new_rel = []
f_path = files_list[0]
# 遍历数据集中的DataFiles
# for f_path in files_list:
for data in open(f_path, 'r', encoding='utf-8'):
tmp = eval(data)
print(tmp)
if len(tmp['nodes']) != 0:
for key, item in tmp['nodes'].items():
item['Choose'] = True
new_node.append(item)
if len(tmp['rels']) != 0:
for key, item in tmp['rels'].items():
item['Choose'] = True
new_rel.append(item)
new_item = [new_node, new_rel]
if len(new_item) == 0:
return '数据为空'
print('NewItem', '成功')
return new_item
Nodes2Graph(dataInput)
函数Nodes2Graph(dataInput)用于将给定的nodes数据添加到已存在的图数据库中。该函数包括以下功能:
-
打开位于openkgdata_root路径下的现有数据库文件(以JSON格式存储)并读取它们的名称。
-
遍历dataInput字典对象中的每个节点,对于每个节点元素,该方法使用create_node构建节点,并检查是否存在相同名称的实体。如果不存在重复实体,则将其添加到图中,并将其属性写入打开的文件中。另外,函数会在新节点上分配一个随机生成的10位原始ID。
-
如果创建不成功,返回None表示该节点已经存在于数据库中。否则,将该节点写入文件。
在此过程中,函数将整理节点的属性,并将其进行重命名为“名称”,以满足已规定好的数据库schema要求。此外,函数还会使用graph参数来创建节点并与数据库交互。这个函数提供了将给定的nodes数据添加到现有图数据库的功能,并将节点属性保存在JSON文件中。需要注意的是,此函数依赖于第三方库py2neo。
# 将json文件中的nodes创建到图谱中
def Nodes2Graph(dataInput):
"""
作用:将json文件中的nodes创建到图谱中
输入:nodes的数据
输出:
"""
data = {}
data['_id'] = {}
o_data = []
f = open(openkgdata_root, 'r', encoding='utf-8')
# 读取openKg数据中所有的名称
for d in f:
d = json.loads(d)
o_data.append(d['名称'])
for key, item in dataInput['nodes'].items():
# 生成随机10位原始ID
# if item['properties']['name'] not in o_data:
ans, oid = create_node(graph, tuple(item['label']), item['properties'])
print('返回None表明创建成功,返回实体数据则表明已存在')
print('ans:',ans)
# 返回None表明创建成功,返回实体数据则表明已存在
if ans == None:
data['_id']['oid'] = oid
for ikey, iitem in item['properties'].items():
data[ikey] = iitem
data['名称'] = data['name']
if item['properties']['name'] not in o_data:
with open(openkgdata_root, 'a', encoding='utf-8') as f:
f.write(json.dumps(data, ensure_ascii=False))
f.write('\n')
print('nodes创建成功')
print('Nodes2Graph', '成功')
return 'nodes创建成功'
Rels2Graph(dataInput)
Rels2Graph(dataInput)用于将给定的rels数据添加到已存在的图数据库中。该函数包括以下步骤:
-
打开位于openkgdata_root路径下的现有数据库文件(以JSON格式存储)并读取它们的名称和标签。
-
遍历传入的rels数据并为每一个关系计算相似度。相似度是通过string_similar函数计算的,并以此决定是否在现有数据库中找到相应的实体节点来构建这些关系。如果相似度足够高,则认为该节点是一致的,并记录下其ID等属性以供稍后使用。
-
准备好所有必要的信息,包括rel_name、start和end节点等,并使用create_relationship函数创建到原始图中的新关系。
在此过程中,数据中的节点属性被视为“名称”,而不是直接的ID等。因此,此功能需要查询现有实体来查找匹配项并获得其正确的ID。函数还会使用graph参数来创建节点并与数据库交互。这个函数提供了将给定的rels数据添加到现有图数据库的功能,以满足数据库schema要求。需要注意的是,此函数依赖于第三方库py2neo。
# 将json文件中的rels创建到图谱中
def Rels2Graph(dataInput):
"""
作用:将json文件中的rels创建到图谱中
输入:rels的数据
输出:
"""
o_data = []
f = open(openkgdata_root, 'r', encoding='utf-8')
data = []
# 读取openKg数据中所有的名称
for d in f:
d = json.loads(d)
if 'label' in d:
o_data.append([d['名称'], d['label']])
else:
o_data.append([d['名称'], [d['类型']]])
for i in dataInput:
tmpRel = {}
tmpRatioS = 0
tmpRatioE = 0
for j in o_data:
similar_ratio_s = string_similar(i['start'], j[0])
similar_ratio_e = string_similar(i['end'], j[0])
if similar_ratio_s > tmpRatioS:
tmpRel['start'] = j
tmpRatioS = similar_ratio_s
if similar_ratio_e > tmpRatioE:
tmpRel['end'] = j
tmpRatioE = similar_ratio_e
tmpRel['rel_name'] = i['rel_name']
data.append(tmpRel)
# [{start:['',[]],end['',[]],rel_name:''},]
print(data)
ans = True
for i in data:
# 生成随机10位原始ID
# item['oid'] = 'r' + str(random.randint(1000000000, 9999999999))
ans = create_relationship(graph, tuple([i['start'][1][0]]), {'name': i['start'][0]},
tuple([i['end'][1][0]]), {'name': i['end'][0]}, i['rel_name'])
print(ans)
return {'msg': '关系数据保存成功'}