进阶向:新手详解Neo4j关系查询代码

      今天我将深入解析一段使用Neo4j图数据库进行关系查询的Python代码。这段代码实现了人物关系查询、知识图谱问答等功能,是图数据库应用的典型示例。我会用最详细的方式讲解每一部分,确保完全理解!

代码概览

这段代码主要包含四个核心功能:

  1. Zquery() - 查询指定人物的所有关系

  2. Zget_json_data() - 将查询结果转换为可视化所需的JSON格式

  3. Zget_KGQA_answer() - 实现知识图谱问答功能

  4. Zget_answer_profile() - 获取人物简介信息

让我们逐行深入解析!

导入依赖模块

from neo_db.Zconfig import graph, CA_LIST, similar_words
from spider.Zshow_profile import get_profile
import codecs
import os
import json
import base64
  • neo_db.Zconfig:自定义模块,包含:

    • graph:Neo4j数据库连接对象

    • CA_LIST:人物类别字典(如{'叶圣陶': '作家'})

    • similar_words:同义词映射字典(如{'朋友': 'friend'})

  • spider.Zshow_profile:自定义爬虫模块,get_profile()函数用于获取人物简介

  • 标准库

    • codecs:文件编码处理

    • os:操作系统接口

    • json:JSON数据处理

    • base64:Base64编码(虽然未使用,但可能用于后续扩展)

核心函数解析

1. Zquery(name) - 查询人物关系

 

def Zquery(name):
    # 构建Cypher查询语句
    query = """
    match(p)-[r]->(n:Person{Name:'%s'}) 
    return p.Name, r.relation, n.Name, p.cate, n.cate
    Union all
    match(p:Person {Name:'%s'})-[r]->(n) 
    return p.Name, r.relation, n.Name, p.cate, n.cate
    """ % (name, name)
    
    # 执行查询并转换为列表
    data = list(graph.run(query))
    
    # 处理并返回JSON格式数据
    return Zget_json_data(data)

 

功能说明

  • 查询与指定人物name相关的所有关系

  • 包含两部分查询(使用UNION ALL合并):

    1. 查找指向该人物的所有关系(谁与TA有关系)

    2. 查找该人物指向其他人的所有关系(TA与谁有关系)

Cypher查询解析

  • match(p)-[r]->(n:Person{Name:'叶圣陶'}):找到所有指向"叶圣陶"的关系

  • match(p:Person{Name:'叶圣陶'})-[r]->(n):找到"叶圣陶"指向他人的关系

  • return返回:起点名称、关系类型、终点名称、起点类别、终点类别

2. Zget_json_data(data) - 数据转换

def Zget_json_data(data):
    # 初始化JSON结构
    json_data = {'data': [], "links": []}
    d = []  # 临时存储节点信息
    
    # 第一步:收集所有唯一节点
    for record in data:
        # 格式:节点名称_类别
        d.append(record['p.Name'] + "_" + record['p.cate'])
        d.append(record['n.Name'] + "_" + record['n.cate'])
    
    # 去重并排序
    d = list(set(d))
    
    # 第二步:创建节点索引映射
    name_dict = {}  # 节点名称->索引的映射
    count = 0
    
    for item in d:
        parts = item.split("_")
        node_name = parts[0]
        
        # 为每个节点创建唯一ID
        name_dict[node_name] = count
        count += 1
        
        # 构建节点数据
        node_data = {
            'name': node_name,
            'category': CA_LIST.get(node_name, 0)  # 从类别字典获取类别
        }
        json_data['data'].append(node_data)
    
    # 第三步:构建关系数据
    for record in data:
        relation = {
            'source': name_dict[record['p.Name']],  # 起点索引
            'target': name_dict[record['n.Name']],  # 终点索引
            'value': record['r.relation']  # 关系类型
        }
        json_data['links'].append(relation)
    
    return json_data

转换过程详解

  1. 节点收集与去重

    • 遍历所有关系记录

    • 提取每条关系的起点和终点(格式:名称_类别

    • 使用set去重,得到所有唯一节点

  2. 节点映射创建

    • 为每个节点分配唯一ID(从0开始递增)

    • 构建节点字典:{节点名称: 索引ID}

    • 创建节点数据:包含名称和类别

  3. 关系数据构建

    • 遍历原始关系数据

    • 使用节点字典将名称转换为索引ID

    • 构建关系对象:起点ID、终点ID、关系类型

最终JSON结构

{
  "data": [
    {"name": "叶圣陶", "category": "作家"},
    {"name": "朱自清", "category": "作家"},
    ...
  ],
  "links": [
    {"source": 0, "target": 1, "value": "朋友"},
    ...
  ]
}

这种格式特别适合前端可视化库(如ECharts)展示知识图谱!

3. Zget_KGQA_answer(array) - 知识图谱问答

 

def Zget_KGQA_answer(array):
    data_array = []  # 存储查询结果
    
    # 示例:['叶圣陶', '朋友', '的'] 
    # 表示查询:叶圣陶的朋友
    for i in range(len(array) - 2):
        # 确定当前查询的起点
        if i == 0:
            current_name = array[0]  # 第一次使用数组第一个元素
        else:
            # 后续使用上一步查询结果的起点
            current_name = data_array[-1]['p.Name']
        
        # 获取关系词的同义词(如'朋友'->'friend')
        relation = similar_words[array[i + 1]]
        
        # 构建查询:查找具有特定关系指向当前人物的节点
        query = """
        match(p)-[r:%s{relation: '%s'}]->(n:Person{Name:'%s'}) 
        return p.Name, n.Name, r.relation, p.cate, n.cate
        """ % (relation, relation, current_name)
        
        # 执行查询
        result = list(graph.run(query))
        data_array.extend(result)
    
    # 返回结果:知识图谱数据 + 最终节点简介
    return [
        Zget_json_data(data_array),  # 转换为可视化格式
        get_profile(str(data_array[-1]['p.Name'])),  # 获取简介
    ]

功能解析

  • 实现多跳关系查询(如"叶圣陶的朋友的朋友")

  • 输入数组格式:[起点, 关系1, 关系2, ...]

  • 处理流程:

    1. 第一跳:查询与起点有"关系1"的所有人

    2. 第二跳:以上一步结果作为新起点,查询有"关系2"的人

    3. 返回最终结果和最后一个人的简介

示例查询

Zget_KGQA_answer(['叶圣陶', '朋友', '的'])

等价于:查找"叶圣陶"的所有"朋友"

4. Zget_answer_profile(name) - 获取人物简介

def Zget_answer_profile(name):
    return [get_profile(str(name))]

简洁的函数,调用爬虫模块获取指定人物的简介信息。

主程序入口

if '__main__' == __name__:
    # 测试知识图谱问答功能
    Zget_KGQA_answer(['叶圣陶', '朋友', '的'])

 

当直接运行脚本时,会执行测试查询:"叶圣陶的朋友"

知识图谱可视化示例

假设我们查询"叶圣陶",可能得到如下知识图谱:

叶圣陶(作家)
│
├── 朋友 → 朱自清(作家)
│
├── 学生 → 钱钟书(作家)
│
└── 合作 → 夏丏尊(教育家)

使用这段代码返回的JSON数据,前端可以轻松渲染出这样的关系图!

学习建议

  1. Neo4j基础

    • 学习Cypher查询语言

    • 理解图数据库的节点、关系、属性概念

  2. 知识图谱构建

    • 如何设计合理的节点和关系类型

    • 数据建模最佳实践

  3. 应用扩展

    • 添加更多查询功能(如关系路径查询)

    • 集成自然语言处理,实现智能问答

    • 结合前端框架实现交互式可视化

总结

这段代码展示了知识图谱应用的几个核心功能:

  1. 使用Cypher进行复杂关系查询

  2. 将图数据转换为可视化友好的JSON格式

  3. 实现多跳关系查询(知识图谱问答)

  4. 整合外部数据源获取详细信息

希望这篇解析对你有帮助!如果有任何问题,欢迎留言讨论。

你可能感兴趣的:(Python进阶,neo4j,pycharm,python)