Neo4j Cypher-比较属性值(如果存在)?

Neo4j Cypher-比较属性值(如果存在)?,neo4j,cypher,Neo4j,Cypher,我有一个很大的图,其中有代表人的节点。它们都有名字和姓氏属性,有些有中间名属性。我在寻找可能代表同一个人的节点,所以我在寻找不同的名称排列。我目前正在比较姓氏和名字的首字母(有些节点只有首字母),但不知道如何测试中间名是否存在 我目前的查询是: match (a:Author), (b:Author) where a.surname=b.surname and ( a.firstname starts with 'A' and b.firstname starts with 'A') r

我有一个很大的图,其中有代表人的节点。它们都有名字和姓氏属性,有些有中间名属性。我在寻找可能代表同一个人的节点,所以我在寻找不同的名称排列。我目前正在比较姓氏和名字的首字母(有些节点只有首字母),但不知道如何测试中间名是否存在

我目前的查询是:

match (a:Author), (b:Author)
where
  a.surname=b.surname and
  ( a.firstname starts with 'A' and b.firstname starts with 'A')
return distinct a,b
我的理解是,可选匹配只涉及模式,所以这不起作用。我找不到一种方法来写一个有意义的if语句

这可能对我来说,通过编程来实现这一点更有意义,而不仅仅是依赖于直接的Cypher查询,但我希望保持它的简单性,只使用Cypher来实现

一些例子来说明我想做什么

例1:

 Node 1:  firstname "John" middlename "Patrick" lastname "Smith" 
    Node 2: firstname "J" middlename "P" lastname "Smith" 
    Node 3: firstname "J" middlename "Q" lastname "Smith" 
    Node 4: firstname "J" lastname "Smith"
我需要一个将节点1、2和4作为“匹配”返回的查询

例2:

Node 1:  firstname "Jane" lastname "Smith" 
Node 2: firstname "J" middlename "P" lastname "Smith" 
Node 3: firstname "J" middlename "Q" lastname "Smith" 
Node 4: firstname "J" lastname "Smith"

在这里,我需要所有4个节点,因为“规范”名称没有中间名。

我认为您需要以下内容:

match (a:Author), (b:Author)
where
  id(a) < id(b) and
  ( a.surname=b.surname) and
  ( a.firstname starts with 'A' and b.firstname starts with 'A') and
  ( a.middlename=b.middlename OR a.middlename IS NULL OR b.middlename IS NULL)
return a,b

这种说法背后有什么原因吗?我现在不能自己测试它。从我对有些不可理解的需求的理解来看,OP想要比较两个都有中间名的人和两个都没有中间名的人。您添加的最后一个子句基本上匹配每个人,除非他们有完全相同的中间名(奇怪?),或者其中一个为零。如果符合OP的模糊要求,您可以这样做。@joslinm是对的,这不是合理的逻辑
a.middlename=b.middlename或a.middlename为NULL或b.middlename为NULL
将返回
true
如果
a.middlename
为NULL或
b.middlename
为NULL,或者它们完全相等,这与伪代码示例相矛盾。仔细想想,我认为我错了。我的答案也一样,只是我没有做太多的比较。道歉!我已经删除了我的答案。您只需在
WHERE
子句中添加
id(a)
就可以改进您的答案,这样您就不会进行重复的比较。您可能希望更清楚地说明您正在尝试做什么,因为“无法找出如何测试中间名(如果它们存在的话)”结果我告诉你使用
EXISTS
并投票支持它。谢谢,希望我的扩展示例能更好地说明问题。FWIW,我没有投你反对票。对我来说,你的评论表明我没有清楚地解释我试图解决的问题。
if (a.middlename is null) return true;
if (b.middlename is null) return true;
if (a.middlename is not null and b.middlename is not null and a.middlename!=b.middlename) return false;
if (a.middlename is not null and b.middlename is not null and a.middlename=b.middlename) return true;