如何在 MERGE 子句中使用 case-insensitive 匹配?
How to use case-insensitive match in MERGE clause?
我有标题中指定的问题。例如,这是我当前的查询:
MERGE (n:Person { name: 'John' })
ON CREATE SET n.age = 30
ON MATCH SET n.age = 30
我想进行 case-insensitive 搜索。所以,name
也许 john, JOHN, joHN
,没关系,它应该仍然匹配。
据我所知,我们可以通过在WHERE
子句中使用正则表达式来实现case-insensitive搜索。例如:
MATCH (n:Person)
WHERE n.name =~ '(?i)John'
但是,MERGE
子句不支持 WHERE
子句。 无效说:
MERGE (n:Person)
WHERE n.name =~ '(?i)John'
ON CREATE SET n.age = 30
ON MATCH SET n.age = 30
那么,这种情况下的解决方案是什么? 我发现的一个建议是 OPTIONAL MATCH
。查询将是:
OPTIONAL MATCH (n:Person) WHERE n.name =~ '(?i)John'
WITH n
WHERE n IS NOT NULL SET n.age = 30
OPTIONAL MATCH (n:Person) WHERE n.name =~ '(?i)John'
WITH n
WHERE n IS NULL MERGE (n:Person { name: 'John', age: 30 })
您如何看待这个解决方案?你有什么建议吗?非常感谢您的帮助。
[编辑]
选项 1.
如果可以向每个 Person
节点添加一个新的 属性 且名称大小写一致(例如,大写),则有一个解决方法。
解决方法要求您首先将新的 属性 添加到所有 Person
节点。例如:
MATCH (p:Person)
SET p.uName = TOUPPER(p.name);
新增属性后,可直接使用MERGE
。 在下面的查询中,我假设您要查找的年龄和姓名作为 parameters $age
和 $name
传递给查询.
MERGE (p:Person {uName: TOUPPER($name)})
ON CREATE SET p.name = $name
SET p.age = $age;
如果节点刚刚创建,此查询设置 name
属性。此外,由于您总是想设置年龄,因此此查询总是这样做。
选项 2.
如果您不想添加新的 属性,您可以使用 APOC 过程 apoc.do.when 选择性地创建 Person
节点并取回选择性创建的节点(或现有节点)对其进行进一步处理。例如:
OPTIONAL MATCH (n:Person)
WHERE n.name =~ ('(?i)' + $name)
CALL apoc.do.when(
n IS NULL,
'CREATE (p:Person {name: $name}) RETURN p',
'RETURN $existing AS p',
{name:$name, existing: n}) YIELD value
WITH value.p AS p
SET p.age = $age
RETURN p;
我有标题中指定的问题。例如,这是我当前的查询:
MERGE (n:Person { name: 'John' })
ON CREATE SET n.age = 30
ON MATCH SET n.age = 30
我想进行 case-insensitive 搜索。所以,name
也许 john, JOHN, joHN
,没关系,它应该仍然匹配。
据我所知,我们可以通过在WHERE
子句中使用正则表达式来实现case-insensitive搜索。例如:
MATCH (n:Person)
WHERE n.name =~ '(?i)John'
但是,MERGE
子句不支持 WHERE
子句。 无效说:
MERGE (n:Person)
WHERE n.name =~ '(?i)John'
ON CREATE SET n.age = 30
ON MATCH SET n.age = 30
那么,这种情况下的解决方案是什么? 我发现的一个建议是 OPTIONAL MATCH
。查询将是:
OPTIONAL MATCH (n:Person) WHERE n.name =~ '(?i)John'
WITH n
WHERE n IS NOT NULL SET n.age = 30
OPTIONAL MATCH (n:Person) WHERE n.name =~ '(?i)John'
WITH n
WHERE n IS NULL MERGE (n:Person { name: 'John', age: 30 })
您如何看待这个解决方案?你有什么建议吗?非常感谢您的帮助。
[编辑]
选项 1.
如果可以向每个 Person
节点添加一个新的 属性 且名称大小写一致(例如,大写),则有一个解决方法。
解决方法要求您首先将新的 属性 添加到所有 Person
节点。例如:
MATCH (p:Person)
SET p.uName = TOUPPER(p.name);
新增属性后,可直接使用MERGE
。 在下面的查询中,我假设您要查找的年龄和姓名作为 parameters $age
和 $name
传递给查询.
MERGE (p:Person {uName: TOUPPER($name)})
ON CREATE SET p.name = $name
SET p.age = $age;
如果节点刚刚创建,此查询设置 name
属性。此外,由于您总是想设置年龄,因此此查询总是这样做。
选项 2.
如果您不想添加新的 属性,您可以使用 APOC 过程 apoc.do.when 选择性地创建 Person
节点并取回选择性创建的节点(或现有节点)对其进行进一步处理。例如:
OPTIONAL MATCH (n:Person)
WHERE n.name =~ ('(?i)' + $name)
CALL apoc.do.when(
n IS NULL,
'CREATE (p:Person {name: $name}) RETURN p',
'RETURN $existing AS p',
{name:$name, existing: n}) YIELD value
WITH value.p AS p
SET p.age = $age
RETURN p;