如何在Cypher中查找集合内含数组属性的对象的索引?
问题:自定义对象集合中使用apoc.coll.indexOf无法获取正确索引
我尝试在自定义对象集合(非节点集合)中查找元素索引,使用apoc.coll.indexOf(collection, object)时返回-1,而非实际索引。
测试查询
首先创建测试节点:
CREATE (test:Test { someArray: [true, false, true] }) CREATE (test2:Test { someArray: [] })
然后尝试获取空数组对象的索引:
MATCH (n:Test) WITH COLLECT({ someArray: n.someArray }) as collection RETURN apoc.coll.indexOf(collection, { someArray: [] }) // 返回-1,预期应为0或1
原因分析
这是预期行为。apoc.coll.indexOf在比较对象时,采用的是引用比较而非值比较。对于数组类型的属性(比如空数组[]),即使两个数组的内容完全一致,它们在Neo4j中的内存引用也是不同的,因此无法匹配到目标元素。
在Neo4j 4.4中,集合、数组这类复杂类型的比较规则就是如此:只有当两个对象是同一个内存引用时,才会被判定为相等;仅值相等但引用不同的对象会被视为不相等,APOC函数的行为遵循了这一底层逻辑。
解决方法
方法1:使用apoc.coll.indexOfWhere自定义匹配逻辑
apoc.coll.indexOfWhere允许你通过自定义条件表达式来匹配元素,避开引用比较的限制。修改后的查询如下:
MATCH (n:Test) WITH COLLECT({ someArray: n.someArray }) as collection RETURN apoc.coll.indexOfWhere(collection, x => x.someArray = [])
这里通过Lambda表达式x => x.someArray = []直接判断元素的someArray属性是否为空数组,能正确返回目标元素的索引。
方法2:将数组转为字符串后比较(适合可序列化的数组内容)
如果数组的内容可以安全转为字符串,可在收集对象时将数组转为字符串形式,这样就能通过值比较匹配:
MATCH (n:Test) WITH COLLECT({ someArrayStr: toString(n.someArray) }) as collection RETURN apoc.coll.indexOf(collection, { someArrayStr: "[]" })
内容的提问来源于stack exchange,提问作者Nils
相关产品推荐
相关产品推荐

