Neo4j查询标签集中的节点集并为每种类型的节点应用where子句...动态

时间:2017-07-28 15:15:16

标签: dynamic neo4j cypher

好的,对于初学者来说,这是一个超长的帖子,所以我道歉。我希望尽可能多地提供我正在做的事情的信息,这样我们就不会浪费时间。

到此为止。我正在基于用户可以在应用程序中创建的一组过滤器(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个节点以及两者之间的任何关系(授予关系endDatenull)。< / 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

好的,到目前为止,一切都很好,花花公子。我得到所有UserfirstName属性以'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子句标准上过滤UserRole节点。我是cypher的初学者,缺乏如何在语法上做这样的事情的基本知识。

1 个答案:

答案 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条件之间。