关于复杂图模式的匹配问题
发布于 6 年前 作者 xiaomei208 2670 次浏览 来自 问答

功能需求是: 输入一个字符串,用一个字符串描述MATCH的模式,这个字符串可以描述一种路径模式,也可以描述一种图模式,目标是返回这个字符串描述的模式的数据(所有的数据,模式中出现的节点和边都要返回)。 现在的思路是: 如果输入的字符串描述的是一种路径模式的话,MATCH P=… RETURN P, 如果输入的字符串描述的是一种图模式的话,比如下面的图,那么我现在想到的是把图拆成路径集合,然后MATCH P1=…,P2=…,P3=…,…. RETURN P1,P2,P3,…。 现在存在的问题是: 输入的字符串是带有正则约束的字符串,约束分两种。 一种是Pat约束,表示对Match的模式进行约束: ?: 表示子表达式出现0或1次. 例如AоB[Pat:?]оC可以是AоC,也可以是AоBоC; : 表示子表达式出现0或n(n≥1)次. 例如A[Pat:]={ ε, A, AоA, AоAоA, …},AоB*оC={AоC, AоBоC, AоBоBоC, AоBоBоBоC, …}; +: 表示子表达式至少出现1次. 例如A[Pat:+]={ A, AоA, AоAоA, …},AоB+оC={AоBоC, AоBоBоC, AоBоBоBоC,…}; (n) (n∈Ν): 表示子表达式出现n次. 例如A [Pat:(n)]={ ■(AоAо…оA@n)}; (m,) (m∈Ν): 表示子表达式至少出现m次. 例如A[Pat:(m,)]={ ■(AоAо…оA@m), ■(AоAо…оA@m+1)…}; (m,n) (m,n∈Ν): 表示子表达式出现m到n次.

例子: PRE:(V:Author)(E:write){(V:Paper)}[Pat:{2,}]〖(E:write)〗^T (V:Author),对(Paper)进行了模式限定,表达的模式是{(V:Author)(E:write)(V:Paper)〖(E:.)(V:Paper)(E:write)〗^T (V:Author),(V:Author)(E:write)(V:Paper)(E:.)(V:Paper)〖(E:.)(V:Paper)(E:write)〗^T (V:Author), (V:Author)(E:write)(V:Paper)(E:.)(V:Paper)(E:.)(V:Paper)〖(E:.)(V:Paper)(E:write)〗^T (V:Author),…}。表达的语义是:作者a写的论文直接引用了作者b写的论文,或者作者a写的论文间接的引用了作者b写的论文。

一种是Ins约束,表示对Match的模式中的某些节点进行实例数量的约束: +: 表示匹配实例至少有1个. 对于PRE“BA[Ins:+]C”,A表示顶点时,可匹配的实例如下:

A表示边时,可匹配的实例如下:

同样,A代表子表达式时,可匹配的实例是B和C之间经过至少一个A表达式的实例。 {n} (n∈Ν): 表示匹配实例n个. 对于PRE“BA[Ins:(n,)]C”,可匹配的实例如下:

A表示边时,可匹配的实例如下:

同样,A代表子表达式时,可匹配的实例是B和C之间经过n个A表达式的实例。

{n,} (n∈Ν): 表示匹配实例至少有n个. 

对于PRE“BA[Ins:(n,)]C”,可匹配的实例如下:

A表示边时,可匹配的实例如下:

同样,A代表子表达式时,可匹配的实例是B和C之间经过至少n个A表达式的实例。 例子: PRE:(V:Author)(E:write){(V:Paper)}[Ins:+]〖(E:write)〗^T (V:Author),对(Paper)进行了Ins限定,表示符合(V:Author)(E:write)(V:Paper)〖(E:write)〗^T (V:Author)模式的实例中,中间(V:Paper)的实例数量必须大于等于1。表达的语义是:作者a和作者b最少合作过一篇论文。 问题:带有Pat约束的模式可以通过构造多条Path实现,但是带有Ins约束的模式怎么实现比较好?(是先拿到不带约束的模式的数据,然后二次处理,在得到的数据中进行COUNT等操作函数筛选数据吗?)我知道Cypher带有COUNT等操作函数,但是采用这种函数的形式,RETURN返回的句子就不能直接用路径p了,需要把模式中的节点和边都返回。

1.png2.png3.png6.png5.png4.png

4 回复

如果我看明白了,你要求的和SQL中的HAVING子句类似。试试下面的方法: 以PRE:(V:Author)(E:write){(V:Paper)}[Ins:+]〖(E:write)〗^T (V:Author)为例, 将整个路径按照有Ins约束的节点分成子路径,然后用WITH + WHERE实现 MATCH path = (a:Author) -[r:Write]- (p:Paper) WITH collect([a,r,p]) AS tuples, count(path) AS cnt WHERE cnt > 1 UNWIND tuples AS t MATCH (t[0]) -[]- (t[1]) …

@graphway 谢谢你的回答。我有问题想要问一下,我这个字符串想表达的查询语义是:找到两个作者论文合作次数超过1次的两作者信息和论文信息,然后你帮忙写的这个cypher,我有点不太理解。你是先查到所有的作者写的论文的数据,然后呢?接下来的操作,我不太懂

@graphway 如果本身的网络结构是这样的:实体类型有用户、评论、餐厅、菜品,用户发表评论,评论分别与餐厅和菜品有连接边,表示针对某家餐厅的评论提到了这家餐厅的某些菜品,餐厅跟菜品之间有连接边。我想要查询的是用户对某家餐厅的某道菜品评价次数超过5次的数据(返回结果包括用户信息、评论信息、餐厅信息和菜品信息)。请问这样的语义查询该怎么写Cypher呢?

如果只是一层关系,那很简单:

MATCH (u:用户) -[:评价]-> (r:餐厅) WHERE u.id = ‘张三’ // 如果要对用户进行筛选 WITH u, count® AS times WHERE times > 5 RETURN u,r 如果关系层次多,那可以参考我上面的回复,分成一段一段。 如果需要理解Cypher的基本用法,可以搜索论坛中的精华文章。

回到顶部