好的,对于初学者来说,这是一个超长的帖子,所以我道歉。我希望尽可能多地提供我正在做的事情的信息,这样我们就不会浪费时间。
到此为止。我正在基于用户可以在应用程序中创建的一组过滤器(where子句)动态构建查询。提供完整的背景信息......
查询开始时看起来像这样:
MATCH (n)
WHERE labels(n) IN $labelsArray
OPTIONAL MATCH (n)-[r]-(entity)
WHERE labels(entity) IN $labelsArray AND
r.endDate IS NULL
RETURN n, r
例如,如果$labelsArray
为['User', 'Role']
,那么查询将在运行时填充,如下所示:
MATCH (n)
WHERE labels(n) IN ['User', 'Role']
OPTIONAL MATCH (n)-[r]-(entity)
WHERE labels(entity) IN ['User', 'Role'] AND
r.endDate IS NULL
RETURN n, r
此查询将返回所有User
个节点,所有Role
个节点以及两者之间的任何关系(授予关系endDate
为null
)。< / p>
好的,这样就行了。但是,如果我想开始应用那些我正在讨论的过滤器(只是一个where子句),该怎么办?我也在动态构建过滤器(用户可以通过应用程序创建过滤器,并将过滤器存储在数据库中)。我查询数据库以构建此过滤器并假设它是第一个过滤器,然后最终它看起来像这样:
AND
(
labels(n) in ['User'] and
n.firstName STARTS WITH 'B'
)
我将此值存储到名为cypherWhere
的变量中。
当我将此过滤器注入原始查询时,它看起来像这样:
MATCH (n)
WHERE labels(n) IN $labelsArray
$cypherWhere <--- added this line
OPTIONAL MATCH (n)-[r]-(entity)
WHERE labels(entity) IN $labelsArray AND
r.endDate IS NULL
RETURN n, r
在运行时看起来像这样:
MATCH (n)
WHERE labels(n) IN ['User', 'Role']
AND
(
labels(n) in ['User'] and
n.firstName STARTS WITH 'B'
)
OPTIONAL MATCH (n)-[r]-(entity)
WHERE labels(entity) IN ['User', 'Role'] AND
r.endDate IS NULL
RETURN n, r
好的,到目前为止,一切都很好,花花公子。我得到所有User
个firstName
属性以'B'
开头的节点。
现在我遇到的问题是应用多个过滤器。假设我有以下两个过滤器:
AND
(
labels(n) in ['User'] and
n.firstName STARTS WITH 'B'
)
AND
(
labels(n) in ['Role'] and
n.displayName = 'Administrator'
)
导致运行时查询:
MATCH (n)
WHERE labels(n) IN ['User', 'Role']
AND
(
labels(n) in ['User'] and
n.firstName STARTS WITH 'B'
)
AND
(
labels(n) in ['Role'] and
n.displayName = 'Administrator'
)
OPTIONAL MATCH (n)-[r]-(entity)
WHERE labels(entity) IN ['User', 'Role'] AND
r.endDate IS NULL
RETURN n, r
此时我真的很兴奋并拍了五个......但等等。我没有收到任何数据。我在网上得分,看看是否有任何关于如何做类似事情的例子并且找不到任何东西。
我假设
的第一个where子句AND
(
labels(n) in ['User'] and
n.firstName STARTS WITH 'B'
)
立即将我的有效负载限制为用户,并且尝试在Role
节点上过滤的第二个where子句没有要过滤的任何角色节点,因为第一个查询剥离了所有不是&#39的节点; ta User
。我不知道我是不对,但我认为这就是正在发生的事情。
好的,回到绘图板,如果我要硬编码,如何编写这个简单的查询。我做了,它看起来像这样:
MATCH (n)
WHERE labels(n) IN ['Role']
AND n.displayName = 'Administrator'
MATCH (a)
WHERE labels(a) IN ['User']
AND a.firstName STARTS WITH 'B'
OPTIONAL MATCH (n)-[r]-(a)
where
r.endDate IS NULL and a.endDate is null
RETURN n, a, r
而中提琴,这会返回我期待的数据。但是有一个问题......我该如何动态地构建这个东西呢?我可以拥有超过2个节点(3,4,5等),所以对它们进行混淆是很困难的。另外,我可以在特定节点类型上使用多个过滤器。在User
个节点上说2个过滤器,在Role
个节点上说一个过滤器等。
我现在有点陷入如何动态构建它的问题上。我向前走的原始路径导致很容易建立动态密码,但我不知道正确的语法来引导我做这样的事情。
任何正文都可以提供一些见解,即使是一些硬编码示例,说明如何在2 where子句标准上过滤User
和Role
节点。我是cypher的初学者,缺乏如何在语法上做这样的事情的基本知识。
答案 0 :(得分:3)
我认为行WHERE labels(n) IN ['User', 'Role']
是错误的(因为您正在测试列表是否在另一个列表中)并且没有必要。
因此,尝试构建一个类似的查询:
MATCH (n)
WHERE
(
'User' IN labels(n) and // fixed here...
n.firstName STARTS WITH 'B'
)
OR // ... here
(
'Role' IN labels(n) and // ...and here.
n.displayName = 'Administrator'
)
OPTIONAL MATCH (n)-[r]-(entity)
WHERE labels(entity) IN ['User', 'Role'] AND
r.endDate IS NULL
RETURN n, r
即:删除行WHERE labels(n) IN ['User', 'Role']
并使用labels(n)
函数修复测试。
此外,由于您尝试取回firstName以“B”开头的所有用户节点以及displayName为“管理员”的角色节点,因此您应使用OR
代替AND
条件之间。