Python调用Neo4j Cypher传入Float变量报KeyError求助
问题排查:Python调用Neo4j point.distance时的KeyError问题
问题描述
在Python中自定义recherche_distance函数,通过Cypher查询调用Neo4j的point.distance计算距离时,传入float类型的lat和longi变量会触发KeyError: 'x '错误,但手动输入数值则运行正常。
报错信息
nosql: <V2_NoSqlDataAccess.NoSqlDataAccess object at 0x000001A283C95BE0> <class 'float'> <class 'float'> lat = 45.438, longi = 4.3862 Traceback (most recent call last): File "c:\Datascientest\neo4j\test_projet\test.py", line 9, in <module> result = nsql.recherche_distance(lat, longi) File "c:\Datascientest\neo4j\test_projet\V2_NoSqlDataAccess.py", line 49, in recherche_distance cypher_query = ''' KeyError: 'x '
相关核心代码
NoSqlDataAccess类的recherche_distance方法
def recherche_distance(self, lat, longi): with self.driver.session() as session: cypher_query = ''' MATCH (s1:Info) WITH point({x : toFloat(s1.latitude), y : toFloat(s1.longitude)}) AS p1, point({x:toFloat({lat}), y:toFloat({longi})}) AS p2, s1 RETURN point.distance(p1,p2) AS Distance, s1.lieu AS Lieu ORDER BY Distance '''.format(lat=lat, longi=longi) result = session.run(cypher_query) return result.fetch(5) self.close()
调用代码
from V2_NoSqlDataAccess import NoSqlDataAccess nsql = NoSqlDataAccess() lat = 45.4380 longi = 4.3862 result = nsql.recherche_distance(lat, longi)
错误原因
Python的str.format()方法会把Cypher语句中定义point的{x : toFloat(s1.latitude)}识别为格式化占位符,试图查找名为x (注意后面的空格)的键,但你只传入了lat和longi两个参数,因此抛出KeyError。
解决方法
方法一:转义Cypher中的大括号
将Cypher语句里用于定义point的{}转义为{{}},保留需要替换的{lat}和{longi}:
def recherche_distance(self, lat, longi): with self.driver.session() as session: cypher_query = ''' MATCH (s1:Info) WITH point({{x : toFloat(s1.latitude), y : toFloat(s1.longitude)}}) AS p1, point({{x:toFloat({lat}), y:toFloat({longi})}}) AS p2, s1 RETURN point.distance(p1,p2) AS Distance, s1.lieu AS Lieu ORDER BY Distance '''.format(lat=lat, longi=longi) result = session.run(cypher_query) return result.fetch(5) self.close()
方法二:使用Neo4j参数化查询(推荐)
直接将参数传给session.run(),无需手动拼接字符串,避免语法冲突和注入风险:
def recherche_distance(self, lat, longi): with self.driver.session() as session: cypher_query = ''' MATCH (s1:Info) WITH point({x : toFloat(s1.latitude), y : toFloat(s1.longitude)}) AS p1, point({x:toFloat($lat), y:toFloat($longi)}) AS p2, s1 RETURN point.distance(p1,p2) AS Distance, s1.lieu AS Lieu ORDER BY Distance ''' result = session.run(cypher_query, lat=lat, longi=longi) return result.fetch(5) self.close()
参数化查询是Neo4j官方推荐的方式,它会自动处理参数类型,同时避免字符串拼接带来的潜在问题。
内容的提问来源于stack exchange,提问作者yannick icard
相关产品推荐
相关产品推荐

