说明
虽然neo4j的cypher里有merge语法,但是这样容易造成一定的逻辑混乱。我愿意多付一点查询代价(发起两次IO),但是确保逻辑的清晰,从而保证程序的可靠性。
内容
cypher提供了一种unwind
方式来进行并行操作,因此只要把数据转为cypher语句就可以了,这里需要用jinja。jinja不能执行多重解析(sas的宏是多重解析的),所以复杂的文本要分批生成。先生成jinja模板,用jinja模板再生成jinja模板。
属性的部分:
str_if_template_obj = "{%% if %s['%s'] %%} %s:'{{%s['%s']}}'{%% endif %%}"
# 数值型变量if模板
num_if_template_obj = "{%% if %s['%s'] %%} %s:{{%s['%s']}}{%% endif %%}"
# !pip install pickle -i https://mirrors.aliyun.com/pypi/simple/
# jinja似乎不能进行多重解析,用python生成部分jinja
# 通常字符型的属性在前
def gen_jinja_attr_list(obj_name , attr_list, attr_type ='str' , keep_last_comma = True):
res =''
for attr in attr_list:
if attr_type.lower() =='str':
tem_res = str_if_template_obj % (obj_name,attr,attr,obj_name,attr)
res = res + tem_res + ','
else:
tem_res = num_if_template_obj % (obj_name,attr,attr,obj_name,attr)
res = res + tem_res + ','
if keep_last_comma:
return res
else:
return res[:-1]
在这里拼起来
from jinja2 import Template
for_start = '{% for node in node_list %}'
loop_if = '{%if not loop.first%},{%endif%}'
end_for = '{% endfor %}'
tier2_str = 'with\
[\
{{for_start}}\
{{loop_if}}\
{\
{{iter_attr}}\
}\
{{end_for}}\
] as data\
UNWIND data as row\
match (n{ {{attr_name}}:row.{{attr_name}} })\
return n.{{attr_name}} as {{attr_name}}\
'
# [{'gnid': 'a001'}, {'gnid': 'a002'}]
# attr_name : gnid
# iter_attr
# "{% if node['gnid'] %} gnid:'{{node['gnid']}}'{% endif %}"
def gen_jinja_query_id(data_list,attr_name, iter_attr, for_start=for_start,loop_if = loop_if,end_for = end_for):
tier2_template = Template(tier2_str)
tier3_str = tier2_template.render(for_start=for_start,loop_if = loop_if,iter_attr =iter_attr,
end_for = end_for,attr_name=attr_name)
return Template(tier3_str).render(node_list=data_list)
#data_list = [{'gnid':'a001'},{'gnid':'a002'}]
#str_attr_list = ['gnid']
#if_attr_list = fs.gen_jinja_attr_list('node', str_attr_list,keep_last_comma=False)
#query_id_cypher = fs.gen_jinja_query_id(data_list,'gnid', if_attr_list)
调用时
data_list = [{'eid':'c1port1'},{'gnid':'a002'}]
str_attr_list = ['eid']
if_attr_list = fs.gen_jinja_attr_list('node', str_attr_list,keep_last_comma=False)
query_id_cypher = fs.gen_jinja_query_id(data_list,'eid', if_attr_list)
结果会返回查到的eid
lneo4j.exe_cypher(query_id_cypher)
---
[{'eid': 'c1port1'}]