基于Neo4j构建的外贸企业关系图谱做企业相似度查询「建议收藏」

基于Neo4j构建的外贸企业关系图谱做企业相似度查询「建议收藏」基于Neo4j的外贸企业关系图谱做企业相似度查询一、外贸企业关系图谱的构建1.从Oracle导出数据2.导入数据到Neo4j3.Neo4j数据展示二、用Cypher做企业关联查询1.多层关系查询2.基于邻居信息的Jaccard相似度计算3.加权关联度得分计算三、总结一、外贸企业关系图谱的构建说来惭愧,本科、研究生期间还没写过博客,正巧最近在写论文,想结合自己开发的项目来构思,于是就通过这篇博客记录一下使用Neo4j图数据库来做企业相似度查询的过程,方便以后参考。这次外贸企业关系图谱的构建用到以前项目中

大家好,又见面了,我是你们的朋友全栈君。

一、外贸企业关系图谱的构建

说来惭愧,本科、研究生期间还没写过博客,正巧最近在写论文,想结合自己开发的项目来构思,于是就通过这篇博客记录一下使用Neo4j图数据库来做企业相似度查询的过程,方便以后参考。
这次外贸企业关系图谱的构建用到以前项目中测试库(Oracle)的数据,导入成csv格式后,再通过python的py2neo导入到neo4j中。
———–由于数据涉及项目的私密信息,暂时就不分享出来了————

1.从Oracle导出数据

该表在Oracle数据库中的部分结构如下:
在这里插入图片描述
目前数据库中的外贸企业数据约30多万条,经过两轮的数据清洗和过滤,我选出了约12万条数据导出,并保存为csv格式。

2.导入数据到Neo4j

Neo4j有自己的csv导入工具,还可以通过cypher语句导入csv格式的数据,但是这里我使用的是pyhon的py2neo库来完成数据的导入。
编写的python代码结构如下:
在这里插入图片描述
下面介绍每个函数的详细代码实现:

'''初始化,用于连接到Neo4j'''
def __init__(self, data):
    self.data = data
    self.g = Graph(
        host="127.0.0.1",  # neo4j 搭载服务器的ip地址
        http_port=7474,  # neo4j 服务器监听的端口号
        user="neo4j",  # 数据库user name
        password="112233") # 密码
'''读取文件'''
def read_nodes(self):
    # 共5类节点
    enterprise = self.data['COMP_NAME_CH']  # 企业
    region = set(self.data['PROVINCE_CH'])  # 地区
    if (np.nan in region):
        region.remove(np.nan)
    country = []  # 出口国家
    for index, row in self.data.iterrows():
        for r in row['EXPORT_COUNTRY_MXT'].split(','):
            country.append(r)
    # 企业类型:1-manufacture-生产型、2-trader-贸易型(贸信通)3-服务型
    enterprise_type = ['生产型', '贸易型', '服务型']  # 企业类型
    legal_representative = self.data['LEGAL_REPRESENTATIVE']  # 法人代表

    # 构建节点实体关系
    rels_region = []  # 企业-地区关系 locate
    rels_country = []  # 企业-出口国家关系 export
    rels_type = []  # 企业-企业类型关系 type
    # rels_product = [] # 企业-产品关系 product
    rels_legal = []  # 企业-法人代表关系 legal
    for index, row in self.data.iterrows():
        if (row['PROVINCE_CH'] is not np.nan):
            rels_region.append([row['COMP_NAME_CH'], row['PROVINCE_CH']])
        for r in row['EXPORT_COUNTRY_MXT'].split(','):
            # 一个企业有多个出口国家
            rels_country.append([row['COMP_NAME_CH'], r])
        rels_type.append([row['COMP_NAME_CH'], '生产型' if row['COMP_TYPE'] == 1\
            else ('服务型' if row['COMP_TYPE'] == 2 else '贸易型')])
        rels_legal.append([row['COMP_NAME_CH'], row['LEGAL_REPRESENTATIVE']])

    return set(enterprise), set(region), set(country), set(enterprise_type), set(legal_representative), \
           rels_region, rels_country, rels_type, rels_legal
'''建立单标签节点'''
def create_node(self, label, nodes):
    count = 0
    for node_name in nodes:
        node = Node(label, name=node_name)
        self.g.create(node)
        count += 1
        print(count, len(nodes))
    return
'''创建知识图谱外贸企业的节点'''
def create_enterprise_nodes(self):
    count = 0
    for index, row in self.data.iterrows():
        node = Node("Enterprise", name=row['COMP_NAME_CH'], credit_code=row['CREDIT_CODE'],
                    setup_time=row['SETUP_TIME'], address=row['ADDRESS_CH'],
                    captial=str(row['REG_CAPITAL']) + '万人民币')
        self.g.create(node)
        count += 1
        print(count)
    return
'''创建实体关联边'''
def create_relationship(self, start_node, end_node, edges, rel_type, rel_name):
    count = 0
    # 去重处理
    set_edges = []
    for edge in edges:
        set_edges.append('###'.join(edge))
    all = len(set(set_edges))
    for edge in set(set_edges):
        edge = edge.split('###')
        p = edge[0]
        q = edge[1]
        query = "match(p:%s),(q:%s) where p.name='%s'and q.name='%s' create (p)-[rel:%s{name:'%s'}]->(q)" % (
            start_node, end_node, p, q, rel_type, rel_name)
        try:
            self.g.run(query)
            count += 1
            print(rel_type, count, all)
        except Exception as e:
            print(e)
    return
'''创建知识图谱实体节点类型schema'''
def create_graphnodes(self):
    # 获取所有节点和关系
    Enterprises, Regions, Countries, Enterprise_types, Legal_representatives, \
    rels_region, rels_country, rels_type, rels_legal = self.read_nodes()
    # 创建图数据库节点
    self.create_enterprise_nodes() # 企业
    self.create_node('Region', Regions) # 地区
    print('地区:' + str(len(Regions)))
    self.create_node('Country', Countries) # 出口国家
    print('出口国家:' + str(len(Countries)))
    self.create_node('Type', Enterprise_types)  #企业类型
    print('企业类型:' + str(len(Enterprise_types)))
    # 暂不需要使用该节点和关系
    # self.create_node('Legal', Legal_representatives) # 法人代表
    # print('法人代表:' + len(Legal_representatives))
    return
'''创建实体关系边'''
def create_graphrels(self):
    # 获取所有关系组
    Enterprises, Regions, Countries, Enterprise_types, Legal_representatives, \
    rels_region, rels_country, rels_type, rels_legal = self.read_nodes()
    self.create_relationship('Enterprise', 'Region', rels_region, 'locate', '所在地区')
    self.create_relationship('Enterprise', 'Country', rels_country, 'export', '出口')
    self.create_relationship('Enterprise', 'Type', rels_type, 'type', '类型')
    # 暂不需要导入该关系
    # self.create_relationship('Enterprise', 'Legal', rels_legal, 'legal', '法人')

最后是main函数:

if __name__ == '__main__':
    # 获取当前路径,并转换为正确格式
    cur_dir = '/'.join(os.path.abspath(__file__).split('\\')[:-1])
    data_path = cur_dir + '/TB_ENTERPRISEINFO_FUSE_BAK.csv'
    print('read_csv from:' + data_path)
    data = pd.read_csv(data_path)
    # 创建实例
    handler = EnterpriseGragh(data)
    # 构建企业图谱的节点和关系
    handler.create_graphnodes()
    handler.create_graphrels()

3.Neo4j数据展示

大约运行了20多小时,终于成功在Neo4j构建好了外贸企业关系图谱,感觉应该是自己在代码优化上可能没有做好=_=||,如果使用Neo4j自带的工具感觉会快上不少。
数据库信息以及查询效果如下图所示:(一共4类节点,3种关系)
在这里插入图片描述

二、用Cypher做企业关联查询

简单查询就不打上来了,感觉有一定参考意义有以下几种查询,可以找到和查询企业关联度最高的企业,作为查询结果。

1.多层关系查询

由于该图数据的有向关系只有一层,所以查询时不能指定关系的方向,这里我们以‘陕西和沃进出口有限公司’为例,查询该企业的多层关系,查询结果如下图:
在这里插入图片描述
对应的Cypher查询语句如下:

match p=(n:Enterprise{name:'陕西和沃进出口有限公司'})-[*2..3]-() return p limit 20

2.基于邻居信息的Jaccard相似度计算

以查询‘陕西和沃进出口有限公司’为例,根据企业的出口国家,计算企业之间的Jaccard相似度,作为相似度衡量标准。(由于Jaccard计算以出口国家关系为基准,所以结果与3.加权关联度得分计算得到的结果不同)
Jaccard的计算公式参考如下:
在这里插入图片描述
根据计算公式,查询到的结果展示如下:
在这里插入图片描述
对应的Cypher查询语句如下:

MATCH (n:Enterprise{name:'陕西和沃进出口有限公司'})-[:export]->(c:Country)<-[:export]-(other:Enterprise)
with n,other,count(c) as intersection,collect(c.name) as collection
match (n)-[:export]->(nc:Country)
with n,other,intersection,collection,collect(nc.name) as s1
match (other)-[:export]->(oc:Country)
with n,other,intersection,collection,s1,collect(oc.name) as s2
with n,other,intersection,s1,s2
with n,other,intersection,s1+filter(x IN s2 where not x IN s1) as uni,s1,s2
return n.name,other.name,s1,s2,((1.0*intersection)/SIZE(uni)) as jaccard
order by jaccard DESC
limit 20

3.加权关联度得分计算

以查询‘陕西和沃进出口有限公司’为例,找到和该企业有相同关系的节点,我们对三种关系企业类型、所在地区、出口国家(type、locate、export)进行加权求和并计算得分,以该得分作为企业相似度的评价标准,可以得到最相关的企业如下。
在这里插入图片描述
对应的Cypher查询语句如下:

MATCH (n:Enterprise) where n.name='陕西和沃进出口有限公司'
match (n)-[:type]->(t:Type)<-[:type]-(other:Enterprise)
with n,other,count(t) as tn
optional match (n)-[:locate]->(r:Region)<-[:locate]-(other)
with n,other,tn,count(r) as rn
optional match (n)-[:export]->(c:Country)<-[:export]-(other)
with n,other,tn,rn,count(c) as cn
return other.name as 推荐企业,tn as 相同企业类型,rn as 相同地区,cn as 相同出口国家,(3*tn)+(3*rn)+(1*cn) as score
ORDER BY score DESC
limit 100

三、总结

以上就是外贸企业关系图谱的构建+查询的整个流程,比较基础。

个人认为可以应用和研究的方向:企业合作伙伴发现、相似企业推荐、投资风险预测、企业市场预测等场景。

看起来像是那么回事奥,但是其实现在论文还没动笔。。。
希望能尽早确定好论文方向,加油!!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/153327.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • VMware虚拟机安装DOS6.22

    VMware虚拟机安装DOS6.22

  • python问题 Traceback (most recent call last)

    python问题 Traceback (most recent call last)python运行问题Traceback(mostrecentcalllast)出现报错traceback(mostrecentcalllast)…………importError:Nomodulenamedlxml解决方案一般是打开cmd执行命令pipinstallxxxx(缺失的包,例如lxml)当然也有例外的,具体可参考下面的问题及其解决…

  • 关于AxisFault的说明[通俗易懂]

    关于AxisFault的说明[通俗易懂]copyfrom:http://tenn.iteye.com/blog/94324一般说来,不可避免的WebService的服务中也会出现异常,举个简单的例子,一个服务接受一个SOAP请求消息,获取有效负载后,进行一个数据库更新操作,而在更新操作过程中发生了SQLException,这个时候就需要告诉客户端(调用WebService)出现异常了,Axis2将异常封装成为一个Axis…

  • 工业数据采集平台

    工业数据采集平台乐芯IOT数据采集平台产品是杭州乐芯科技有限公司为满足工业4.0大型集团工厂推出的新一代数据采集平台级产品,可满足单一平台(一个服务器)同时采集各类设备,同时兼容各种协议,单服务器压力测试达1000台,已经稳定在大型集团用户稳定运行。实现各种工业设备数据采集,包括数控机床数据采集、切割机数据采集、机器人数据采集、PLC数据采集、各种工业仪表(各类传感器、智能电表等)。并实现数据对接各大工业平台(如:根云平台、施耐德平台、阿里云平台等)。

  • log4cpp 使用完全手册「建议收藏」

    log4cpp 使用完全手册「建议收藏」原文链接 点击打开链接一、log4cpp概述     Log4cpp是一个开源的C++类库,它提供了C++程序中使用日志和跟踪调试的功能,它的优点如下:提供应用程序运行上下文,方便跟踪调试;可扩展的、多种方式记录日志,包括命令行、文件、回卷文件、内存、syslog服务器、Win事件日志等;可以动态控制日志记录级别,在效率和功能中进行调整;所有配置可以通过配置文件进行动态调整;多语言支持,包括Ja…

  • PHP审计之POP链挖掘

    PHP审计之POP链挖掘前言续上文中的php反序列化,继续来看,这个POP的挖掘思路。在其中一直构思基于AST去自动化挖掘POP链,迫于开发能力有限。没有进展,随后找到了一个别的师傅已经实现好的项

    2021年12月13日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号