+
+ def recursive_find(key_list, key_next_index, content, oper, target):
+ if key_next_index == len(key_list) or content is None:
+ try:
+ if oper in ("eq", "cont"):
+ if isinstance(target, list):
+ if isinstance(content, list):
+ return any(content_item in target for content_item in content)
+ return content in target
+ elif isinstance(content, list):
+ return target in content
+ else:
+ return content == target
+ elif oper in ("neq", "ne", "ncont"):
+ if isinstance(target, list):
+ if isinstance(content, list):
+ return all(content_item not in target for content_item in content)
+ return content not in target
+ elif isinstance(content, list):
+ return target not in content
+ else:
+ return content != target
+ if oper == "gt":
+ return content > target
+ elif oper == "gte":
+ return content >= target
+ elif oper == "lt":
+ return content < target
+ elif oper == "lte":
+ return content <= target
+ else:
+ raise DbException("Unknown filter operator '{}' in key '{}'".
+ format(oper, ".".join(key_list)), http_code=HTTPStatus.BAD_REQUEST)
+ except TypeError:
+ return False
+
+ elif isinstance(content, dict):
+ return recursive_find(key_list, key_next_index + 1, content.get(key_list[key_next_index]), oper,
+ target)
+ elif isinstance(content, list):
+ look_for_match = True # when there is a match return immediately
+ if (target is None) != (oper in ("neq", "ne", "ncont")): # one True and other False (Xor)
+ look_for_match = False # when there is not a match return immediately
+
+ for content_item in content:
+ if key_list[key_next_index] == "ANYINDEX" and isinstance(v, dict):
+ matches = True
+ for k2, v2 in target.items():
+ k_new_list = k2.split(".")
+ new_operator = "eq"
+ if k_new_list[-1] in ("eq", "ne", "gt", "gte", "lt", "lte", "cont", "ncont", "neq"):
+ new_operator = k_new_list.pop()
+ if not recursive_find(k_new_list, 0, content_item, new_operator, v2):
+ matches = False
+ break
+
+ else:
+ matches = recursive_find(key_list, key_next_index, content_item, oper, target)
+ if matches == look_for_match:
+ return matches
+ if key_list[key_next_index].isdecimal() and int(key_list[key_next_index]) < len(content):
+ matches = recursive_find(key_list, key_next_index + 1, content[int(key_list[key_next_index])],
+ oper, target)
+ if matches == look_for_match:
+ return matches
+ return not look_for_match
+ else: # content is not dict, nor list neither None, so not found
+ if oper in ("neq", "ne", "ncont"):
+ return target is not None
+ else:
+ return target is None
+