在OPTIONAL MATCH查询中使用COUNT()获取不正确的值

时间:2017-10-26 20:51:40

标签: neo4j cypher

好的,这是我的数据模型:

(User)-[:ASSIGNED_TO]-(Account)
(Location)-[:BELONGS_TO]->(Account)
(User)-[:ASSIGNED_TO]-(Location)

在我的数据库中有1个帐户,1个位置和16个用户。每个用户都是:ASSIGNED_TO帐户,:ASSIGNED_TO位置。位置:BELONGS_TO帐户。

我尝试按ID选择特定帐户,并返回该帐户的用户和位置数。这是我的疑问:

MATCH (account:Account)
WHERE account.id = '123456'
WITH account
OPTIONAL MATCH (location:Location)-[:BELONGS_TO]->(account)
OPTIONAL MATCH (user:User)-[:ASSIGNED_TO]->(account)
RETURN account, count(location) as locationCount, count(user) as userCount

结果是accountuserCount = 16 (correct)locationCount = 16 (incorrect; should be 1)。如果我将distinct添加到位置计数count(distinct location),我会得到正确的结果(1),如果我删除了用户的OPTIONAL MATCH,我的位置数也会为1。我知道这与与帐户和位置有关系的用户有关,但我只是想了解为什么没有明显的查询不起作用。还有,有更好的方法来写这个吗?

3 个答案:

答案 0 :(得分:1)

这确实有点棘手。这是重写的查询,以显示您正在寻找的模式:

MATCH (account:Account)
WHERE account.id = '123456'
MATCH (location:Location)-[:BELONGS_TO]->(account)<-[:ASSIGNED_TO]-(user:User)
RETURN account, count (location), count (user)

中间有一个帐户,但你不知道每边的数字是多少。 结果集将包含模式的所有匹配项(恰好是16,但可能有更多位置和用户分配到多个位置)。所以实际上 计数都不正确(你只是对用户来说很幸运)。

MATCH (account:Account)
WHERE account.id = '123456'
MATCH (location:Location)-[:BELONGS_TO]->(account)<-[:ASSIGNED_TO]-(user:User)
RETURN account, count (DISTINCT location), count (DISTINCT user)

DISTINCT解决了这个问题。按帐户聚合(只有一个没有真正的聚合发生),结果集中有16个位置。 DISTINCT确保您只计算独特的数量。同样的DOES也适用于用户!

看看这个查询,看看差异:

MATCH (account:Account)
WHERE account.id = '123456'
MATCH (location:Location)-[:BELONGS_TO]->(account)
RETURN account.id as id, "location count" as type, count(location) as ct
UNION
MATCH (account:Account)
WHERE account.id = '123456'
MATCH (account)<-[:ASSIGNED_TO]-(user:User)
RETURN account.id as id, "user count" as type, count(user) as ct

希望这有帮助。

此致 汤姆

答案 1 :(得分:0)

如果您在行而不是图表中查看结果,则可以看到实际上有16行数据。每行包含locationcount(location)实际上返回的行数为location

我更喜欢使用distinct来删除重复项。我们在生产中提供服务,我们在类似的情况下使用distinct

答案 2 :(得分:0)

我遇到了类似的问题,它有助于从RDBMS的角度来考虑它。

考虑一个像这样的用户表(我的例子中使用4):

Users
-----
u1
u2
u3
u4

并考虑2个位置和账户表(每个都有一个记录,如你的情况):

Locations
---------
loc1

Accounts
--------
acc1

现在,当Neo4j评估MATCH (location:Location)-[:BELONGS_TO]->(account)<-[:ASSIGNED_TO]-(user:User)之类的查询时,它会开始查找User个节点和Location个节点,并且会向内跟踪Account个节点之间的关系。然后执行连接。因此,要将该查询分解为中间查询,它将如下所示:MATCH (location:Location)-[:BELONGS_TO]->(account)MATCH (account)<-[:ASSIGNED_TO]-(user:User)。评估这两个查询会给我们类似下表:

Location-Account
----------------
loc1 | acc1

Account-User
------------
u1 | acc1
u2 | acc1
u3 | acc1
u4 | acc1

最后,Neo4j对中间结果执行连接,返回类似下面的组合表:

User-Account-Location
---------------------
u1 | acc1 | loc1
u2 | acc1 | loc1
u3 | acc1 | loc1
u4 | acc1 | loc1

count(location)根据此表格为4,而count(DISTINCT(location))为1:)

相关问题