抗疫期间,为帮助广大民众解除是否与病毒患者近距离接触过的困惑,微云数聚(北京)科技有限公司利用图数据库技术和官方报导的数据,及时研发并推出了《疫情搜》工具,方便大家快速查到涉疫的交通工具和地点。该工具在 头条的报导 后被推荐了数千次。应众多图粉的要求,本文将公开该工具实现的技术细节,包括数据来源、采集抽取、图数据建模以及 完整的导入语句 ,供图数据库、知识工程等相关技术人员参考。 全是干货!
一、需求分析
中国正面临着一场前所未见的疫情。各种交通工具已成为病毒传播的一种主要途径。春节期间回家探亲、返城复工又不得不乘坐飞机、火车、长途客车、公共汽车、地铁、轮船、出租车等交通工具,难免有与病毒患者同行的机会。关于确诊病人乘坐过的飞机、火车等情况,各级政府和新闻机构有许多报导。如何从大量的报导中查出自己乘坐过的交通工具是否有确诊病例乘坐过?这就亟需一个便利的查询工具。 近期有 很多技术志愿者纷纷推出了各种“同行查询”工具,但尚未见到既能快速查询、又能直观展现传播途径的工具。《疫情搜》就是为满足这个实际需求研发而成的。
二、功能设计
想知道你是否曾经与病毒患者同坐过飞机、火车、地铁或同到过某个地点吗?只需点击 http://v.we-yun.com:2020 输入地名(如“北京”,“北京,武汉”、“北京,武汉,上海”等)、航班、车次或车牌等即可迅速查到。 友情提示: 首次进入较慢,请耐心等待一下。
查询举例:
1、输入“ 北京“,查询与北京相关的涉疫情航班、车次、车牌
2、输入“ 北京,武汉“,查询与北京与武汉相关的涉疫情航班、车次、车牌
3、输入“ 北京,武汉,上海 “,查询与北京、武汉和上海相关的涉疫情航班、车次、车牌
三、架构设计
数据库:图数据库 Neo4j Enterprise 3.5.14,单实例 插件:apoc-3.5.0.6-all.jar 应用层:关系搜 3.5.14
四、数据源
网站: https://2019ncov.nosugartech.com 数据: https://2019ncov.nosugartech.com/data.json
五、数据建模
设立飞机、火车、长途、公交、轮船、出租、场所和地点共8种(对象)节点,前7种(对象)节点与地点有出发和到达(关系)连线。
六、完整的导入语句(干货来了)
// 删除全文索引
call db.indexes() yield type, indexName where type='node_fulltext' and indexName='名称'
call db.index.fulltext.drop(indexName) return *;
// 创建全文索引
call db.index.fulltext.createNodeIndex("名称",["地点","飞机","火车", "地铁", "长途", "公交", "出租", "轮船", "场所"],["名称"]);
CREATE CONSTRAINT ON (p:地点) ASSERT p.名称 IS UNIQUE;
// 清除数据
match (n:地点) detach delete n;
// 导入传播数据
WITH "https://2019ncov.nosugartech.com/data.json" AS url
CALL apoc.load.json(url) YIELD value
UNWIND value.data AS item
//创建事件节点
with item,
['飞机', '火车', '地铁', '长途', '公交', '出租', '轮船', '场所'][item.t_type-1] as type,
['航班', '车次', '线号', '车牌', '车牌', '车牌', '船次', '名称'][item.t_type-1] as no_name
call apoc.merge.node([type], {id:item.id},
{
名称:item.t_no + case when item.t_no_sub='' then '' else ' ' + item.t_no_sub end,
类型:type,
日期:item.t_date,
开始时间:item.t_start,
结束时间:item.t_end,
出行类型:type,
出行描述:item.t_memo,
车厢:item.t_no_sub,
出发站:item.t_pos_start,
到达站:item.t_pos_end,
线索来源:item.source,
线索人:item.who,
更新时间:item.updated_at,
image:'http://we-yun.com/image/交通工具/'+type+'.png'
},
{}) yield node
//创建开始节点
with item, node where item.t_pos_start<>''
merge (p1:地点 {名称:item.t_pos_start})
//创建结束节点
with item, node, p1 where item.t_pos_end<>'' and item.t_pos_start<>item.t_pos_end
merge (p2:地点 {名称:item.t_pos_end})
// 创建出发和到达关系
merge (p1)-[r1:出发]->(node)-[r2:到达]->(p2)
return count(r2);
// 设置节点显示属性
with [
{ color: '#FFE081', `border-color`: '#9AA1AC', `text-color-internal`: '#FFFFFF'},
{ color: '#C990C0', `border-color`: '#b261a5', `text-color-internal`: '#FFFFFF'},
{ color: '#F79767', `border-color`: '#f36924', `text-color-internal`: '#FFFFFF'},
{ color: '#57C7E3', `border-color`: '#23b3d7', `text-color-internal`: '#FFFFFF'},
{ color: '#F16667', `border-color`: '#eb2728', `text-color-internal`: '#FFFFFF'},
{ color: '#D9C8AE', `border-color`: '#c0a378', `text-color-internal`: '#604A0E'},
{ color: '#8DCC93', `border-color`: '#5db665', `text-color-internal`: '#604A0E'},
{ color: '#ECB5C9', `border-color`: '#da7298', `text-color-internal`: '#604A0E'},
{ color: '#4C8EDA', `border-color`: '#2870c2', `text-color-internal`: '#FFFFFF'},
{ color: '#FFC454', `border-color`: '#d7a013', `text-color-internal`: '#604A0E'},
{ color: '#DA7194', `border-color`: '#cc3c6c', `text-color-internal`: '#FFFFFF'},
{ color: '#569480', `border-color`: '#447666', `text-color-internal`: '#FFFFFF'}
] as nodeSettings
MATCH (n:地点)
with nodeSettings, n, apoc.node.degree(n, '<') as cnt_in, apoc.node.degree(n, '>') as cnt_out
with nodeSettings, n, cnt_in, cnt_out,
case when cnt_out=0 then 11 when cnt_out<5 then 3 else 10 end as index
set n.diameter=80+cnt_out*100/500, n+=nodeSettings[index],
n.传出次数=cnt_out,
n.传入次数=cnt_in,
n.caption=n.名称+'('+cnt_in+","+cnt_out+')';
七、特别鸣谢
感谢 《新型冠状病毒肺炎确诊患者同行程查询工具》的作者整理和无私分享数据! 感谢庞国明先生推荐 数据源,以及他研究病毒传播模型带給我研发《疫情搜》的灵动!