这里的重复节点指的是一个label下的部分节点,属性A相同,其他属性不相同
问题背景:
本文中的数据为举例说明,实际数据不便展示,但表达的意思一致;
1. neo4j中label为PERSON的的节点有name和wechat两个属性,关系type为FRIEND;
2. 在进行数据的清洗和预处理过程中,name对应的wechat数据获取出现偏差,导致一个name在先后获取wechat时取到了不同的值,导致一个人员录入了两个节点,如name=Tom前后获取wechat时分别获取到了123和456两个值,最终在neo4j中存储的节点有两个:
(:PERSON{name:"Tom",wechat:"123"}) (:PERSON{name:"Tom",wechat:"456"})
3. 导入的关系数据是以name为参照建立的,比如 Tom 和 Jerry 为 FRIEND 关系,由于节点信息的错误,则在库中将存在两个关系,但实际只应存在一个有效关系:
(:PERSON{name:"Tom",wechat:"123"})-[:FRIEND]-(:PERSON{name:"Jerry",wechat:"111"}) (:PERSON{name:"Tom",wechat:"456"})-[:FRIEND]-(:PERSON{name:"Jerry",wechat:"111"})
3. 优化数据清洗和预处理程序后,能确保获取到唯一一个wechat值,这时neo4j中已经导入了千万级节点和关系,重新导入的话耗时太长;
解决方案:
1. 节点中name对应的wechat可能会有多个值,但后面的数据分析只需要一个即可,由于节点和关系都是批量导入的,所以同样是name="Tom"的节点,先导入的节点对应的关系将会多于后导入的节点对应的关系;
2. 解决方案为删除name属性相同的重复节点,保留重复节点中第一个录入的节点,后面录入的节点及其关系删除;
实施步骤:
1. 查看库中是否存在重复节点:
# 查询节点总数
match (n:PERSON) return count(n)
# 查询一个属性的去重数量
match (n:PERSON) return count(distinct n.name) # 比较总数和去重后总数可判断是否存在相同name的节点
2. 获取重复节点的详细信息:
# 查询返回name相同但是节点ID不同的节点,n与m即为重复节点
match (n:PERSON),(m:PERSON) where n.name=m.name and id(n)<>id(m) return n,id(n),m,id(m);
# 比较重复节点的关系数量可只最先录入的节点的关系最为完整最多,后面录入的节点会缺少部分关系
# 以上一查询中返回的重复节点 id=12 和 id=460964 进行比较
match (n:PERSON)-[:FRIEND]-(m:PERSON) where id(n)=12 rerurn count(m);
match (n:PERSON)-[:FRIEND]-(m:PERSON) where id(n)=46096 rerurn count(m);
3. 获取每条重复节点记录中的id较大值,删除该节点及节点所有关系:
match (n:PERSON)-[r:FRIEND]-(:PERSON) where id(n)=46096 delete n,r;