Neo4j 返回与具有特定属性的其他节点连接最多的节点

Neo4j 返回与具有特定属性的其他节点连接最多的节点,neo4j,cypher,Neo4j,Cypher,我的消息图中有以下关系: (m:Message)-[:ORIGINATED_AT]->(i:IP)-[:IN_NETWORK]-(n:Network) 我试图找到IP和网络发送的邮件最多,类别为“垃圾邮件” 我尝试了以下查询: // IPs sending the most spam: match (ip:IpAddress)--(m:Message) where toLower(m.category) contains 'spam' with ip, size(()-[:ORIGINA

我的消息图中有以下关系:

(m:Message)-[:ORIGINATED_AT]->(i:IP)-[:IN_NETWORK]-(n:Network)
我试图找到IP和网络发送的邮件最多,类别为“垃圾邮件”

我尝试了以下查询:

// IPs sending the most spam:
match (ip:IpAddress)--(m:Message)
where toLower(m.category) contains 'spam'
with ip, size(()-[:ORIGINATED_AT]->(ip)) as volume
ORDER BY volume DESC LIMIT 10
match (ip)--(net:Network)
return ip, net
但它似乎找到了“发送最多邮件的网络至少有一条垃圾邮件”,但我想要的是“发送最多垃圾邮件的网络”。此外,查询返回的结果少于10个预期结果

我删除了message变量以使IP发送的消息最多,这似乎与预期的一样:

// IPs sending the most messages:
match (ip:IpAddress)
with ip, size(()-[:ORIGINATED_AT]->(ip)) as volume
ORDER BY volume DESC LIMIT 10
match (ip)--(net:Network)
return ip, net

我如何修改我的查询,以便只正确计算相关(m:Message)具有“垃圾邮件”类别的关系?

我认为您的思路是正确的,您只是把它复杂化了一点。您只需要对每个IP地址包含“垃圾邮件”的每封邮件进行计数

MATCH (ip:IpAddress)--(m:Message)
WHERE toLower(m.category) contains 'spam'
RETURN ip, count(m) AS spam_messages
ORDER BY spam_messages DESC LIMIT 10
要在这种情况下使用
size()
,请将
count()
替换为另一个聚合函数
collect()
,该函数将元素放入列表或集合中,而不是对它们进行计数。然后使用
size()
返回列表中的项目数。如果您需要实际元素本身进行某种后期处理,这种方法将非常有用

MATCH (ip:IpAddress)--(m:Message)
WHERE toLower(m.category) contains 'spam'
WITH ip, collect(m) AS spam_messages
RETURN ip, size(spam_messages) as spam_messages_size
ORDER BY spam_messages_size DESC LIMIT 10

简单且工作完美。什么时候使用
count()
,什么时候使用
size()
在任何一种情况下都可以使用,是否有一个经验法则?它们不是很简单
count()
是一个聚合函数。而
size()是一个列表函数
。我将更新答案以说明差异。