我正在导入和操作一些深层嵌套的JSON(作为字典导入)。它可以使用以下代码分配值:
query['query']['function_score']['query']['multi_match']['operator'] = 'or'
query['query']['function_score']['query']['multi_match'].update({
'minimum_should_match' : '80%' })
但是它像坚果一样丑陋而笨重。我想知道是否有一种更清晰的方法可以为深度嵌套的密钥分配值,并且效率相当高?
我已经读过有关可能使用内存中的SQLlite数据库的信息,但是经过一些操作后数据又回到了json中。
答案 0 :(得分:3)
multi_match = query['query']['function_score']['query']['multi_match']
multi_match['operator'] = 'or'
multi_match.update({'minimum_should_match' : '80%' })
答案 1 :(得分:2)
JSONPath(通过' jsonpath_rw')使它不那么麻烦:
一个:
>>> query
{u'query': {u'function_score': {u'query': {u'multi_match': {u'min_should_match': u'20%'}}}}}
更新
>>> found = jsonpath_rw.parse("$..multi_match").find(query)[0]
>>> found.value["operator"] == "or"
>>> found.value["min_should_match"] = "80%"`
然后:
>>> query
{u'query': {u'function_score': {u'query': {u'multi_match': {'min_should_match': '80%', u'operator': u'or'}}}}}
答案 2 :(得分:0)
选择的答案肯定是要走的路。我(稍后)发现的问题是我的嵌套密钥可以出现在不同的级别。所以我需要能够遍历dict并首先找到节点的路径,然后进行更新或添加。
jsonpath_rw是最直接的解决方案,但我尝试使用它时得到了一些奇怪的结果。经过几个小时的摔跤,我放弃了。
冒着成为一个笨重的新手而被击落的风险,我最终充实了一些功能(基于我在SO上找到的其他代码),这些功能原生地做了一些很好的事情来满足我的需求:
def find_in_obj(obj, condition, path=None):
''' generator finds full path to nested dict key when key is at an unknown level
borrowed from http://stackoverflow.com/a/31625583/5456148'''
if path is None:
path = []
# In case this is a list
if isinstance(obj, list):
for index, value in enumerate(obj):
new_path = list(path)
new_path.append(index)
for result in find_in_obj(value, condition, path=new_path):
yield result
# In case this is a dictionary
if isinstance(obj, dict):
for key, value in obj.items():
new_path = list(path)
new_path.append(key)
for result in find_in_obj(value, condition, path=new_path):
yield result
if condition == key:
new_path = list(path)
new_path.append(key)
yield new_path
def set_nested_value(nested_dict, path_list, key, value):
''' add or update a value in a nested dict using passed list as path
borrowed from http://stackoverflow.com/a/11918901/5456148'''
cur = nested_dict
path_list.append(key)
for path_item in path_list[:-1]:
try:
cur = cur[path_item]
except KeyError:
cur = cur[path_item] = {}
cur[path_list[-1]] = value
return nested_dict
def update_nested_dict(nested_dict, findkey, updatekey, updateval):
''' finds and updates values in nested dicts with find_in_dict(), set_nested_value()'''
return set_nested_value(
nested_dict,
list(find_in_obj(nested_dict, findkey))[0],
updatekey,
updateval
)
find_in_obj()是一个生成器,用于查找指定嵌套键的路径。
set_nested_values()将在给定列表的dict中更新键/值,或者如果它不存在则添加。
update_nested_dict()是"包装器"对于嵌套字典中要搜索的两个函数,您要查找的密钥以及要更新的密钥值(如果它不存在则添加)。
所以我可以传入:
q = update_nested_dict(q, 'multi_match', 'operator', 'or')
q = update_nested_dict(q, 'multi_match', 'minimum_should_match', '80%')
"运营商"值已更新,并且" minimum_should_match'键/值添加在' multi_match'节点,无论它出现在字典中的哪个级别。
如果搜索到的密钥存在于字典中的多个位置,则可能会遇到问题。