背景
使用neo4j过程遇到的一个复杂提数需求
数据类型:pin是用户,category是用户关联的类目,类目分为一二三级类目,category之间还有关联,其中还有个象征全部的WildcardCategory节点(先不用理解)
数据逻辑:需要提取pin关联的全部类目数据,如果pin对有关系的类目都进行了关联,则取有关系类目中的最高级(级别依次降低顺序,1最高:1--》2--》3)数据表示,比如:如果pin同时关联了一级类目和二级类目,那么只记录关联的一级类目数据,目的简化要提取的数据情况。
数据演示过程
初始化数据cql
//创建用户
create (:Pin{name:"pin1"});
//创建类目
create (:Category{code:"11",level:1});
create (:Category{code:"12",level:1});
create (:Category{code:"13",level:1});
create (:Category{code:"21",level:2});
create (:Category{code:"22",level:2});
create (:Category{code:"221",level:2});
create (:Category{code:"23",level:2});
create (:Category{code:"24",level:2});
create (:Category{code:"31",level:3});
create (:Category{code:"32",level:3});
create (:Category{code:"33",level:3});
create (:Category{code:"331",level:3});
create (:Category{code:"34",level:3});
//创建代表全部类目的节点
create (:WildcardCategory{name:"category"});
//创建类目之间的关系
match (c1:Category),(c2:Category) where c1.code="11" and c2.code="21" create (c1)-[:IS_PARENT_OF]->(c2);
match (c1:Category),(c2:Category) where c1.code="21" and c2.code="31" create (c1)-[:IS_PARENT_OF]->(c2);
match (c1:Category),(c2:Category) where c1.code="12" and c2.code="22" create (c1)-[:IS_PARENT_OF]->(c2);
match (c1:Category),(c2:Category) where c1.code="12" and c2.code="221" create (c1)-[:IS_PARENT_OF]->(c2);
match (c1:Category),(c2:Category) where c1.code="22" and c2.code="32" create (c1)-[:IS_PARENT_OF]->(c2);
match (c1:Category),(c2:Category) where c1.code="13" and c2.code="23" create (c1)-[:IS_PARENT_OF]->(c2);
match (c1:Category),(c2:Category) where c1.code="23" and c2.code="33" create (c1)-[:IS_PARENT_OF]->(c2);
match (c1:Category),(c2:Category) where c1.code="23" and c2.code="331" create (c1)-[:IS_PARENT_OF]->(c2);
//创建用户和类目之间的关系
match (p:Pin),(c:Category) where p.name="pin1" and c.code in ["11","21","31","12","22","23","33","34"] create (p)-[:ALLOW]->(c);
//创建用户和全量类目的关系
match (p:Pin),(w:WildcardCategory) where p.name="pin1" create (p)-[:JOIN]->(w);
橘黄色是pin用户,蓝色是category类目,红色是全部类目节点,使用上面的语句可以初始化出来下面的数据情况
分析:不同红框内是要导出的不同数据,比如1、2、3都连的只导出1的数据,同时连1、2的只导出1,同时连2、3的只导出2,类目之间没有关联的单节点都导出,象征全部的节点也都导出。
导出cql
//查询关联一级类目的数据
match (p:Pin)-[:ALLOW]-(c:Category{level:1})
return distinct p.name as name,c.code as code,c.level as level,null as hasWildcardCategory order by p.name,c.level
union
//查询关联二级类目并且没有关联一级类目的数据
match (p:Pin)-[:ALLOW]-(c:Category{level:2})<-[:IS_PARENT_OF]-(cc:Category{level:1})
where not (p)-[:ALLOW]-(cc)
return distinct p.name as name,c.code as code,c.level as level,null as hasWildcardCategory order by p.name,c.level
union
//查询关联三级类目并且没有关联一、二级类目的数据
match (p:Pin)-[:ALLOW]-(c:Category{level:3})<-[:IS_PARENT_OF]-(cc:Category{level:2})<-[:IS_PARENT_OF]-(ccc:Category)
where not (p)-[:ALLOW]-(cc) and not (p)-[:ALLOW]-(ccc)
return distinct p.name as name,c.code as code,c.level as level,null as hasWildcardCategory order by p.name,c.level
union
//数据兼容处理:可能存在一二三类目之间关系缺少的情况,查询没有关联任何上级类目的二三级类目
match (p:Pin)-[:ALLOW]-(c:Category)
where c.level in [2,3] and not (c)-[:IS_PARENT_OF]-(:Category)
return distinct p.name as name,c.code as code,c.level as level,null as hasWildcardCategory order by p.name,c.level
union
//查询用户是否关联了全部类目,因为是另外一种label,所以也需要查询出来
match (p:Pin)-[:JOIN]->(w:WildcardCategory)
return distinct p.name as name,null as code,null as level,"关联全部类目" as hasWildcardCategory
导出结果,完全正确,导出了pin关联的数据,也简化了导出的数据量