虽然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'}]