Skip to content

Instantly share code, notes, and snippets.

@sheki
Last active December 23, 2015 07:59
Show Gist options
  • Select an option

  • Save sheki/6604949 to your computer and use it in GitHub Desktop.

Select an option

Save sheki/6604949 to your computer and use it in GitHub Desktop.
The algorithm to flatten MongoQueries so that they can be represented by a single query key
# Converts a Query JSON into a flat key.
#{
# "where": {
# "activityDistance": {
# "$gte": 2.5
# },
# "accumulatedTotalDistance": {
# "$lte": 10695
# },
# "
# "order": "-createdAt",
#}
# to a flat key like :
# "{\"$OR\": [{\"_acl\": {\"$exists\": \"\"}}, {\"_acl.*.r\": \"\"}]}"
ARRAY_QUERY_SET = Set(["$in", "$nin", "$box", "$nearSphere", "$all", "$within"])
class SimpleQueryAST:
""" represent a query ast in a simplified manne """
def __init__(self, json):
self._simple_where_keys = [] # simple where clauses
self._where_in_keys = [] # keys with where in clause
self._other_keys = [] # ignored for now.
self._or_keys = [] # or keys
self.collection_name = ""
self.app_key = ""
self.__flatten_json(json)
self._where_in_keys.sort()
self._simple_where_keys.sort()
self._other_keys.sort()
self._or_keys.sort()
def __remove_values(self,json_obj):
result = {}
for k,v in json_obj.items():
if type(v) == dict:
result[k] = self.__remove_values(v)
elif k == "$or":
assert type(v) == list
temp = []
for item in v:
temp.append(self.__remove_values(item))
result["$OR"] = temp
elif k in ARRAY_QUERY_SET:
return "$ARRAY_QUERY"
elif type(v) == str or type(v) == int or type(v) == float or isinstance(v, datetime.datetime) or type(v) == bool or type(v) == unicode or v == None:
result[k] = ""
else:
sys.stderr.write("COULD NOT UNDERSTAND THE OBJECT %s\n".format(str(json_obj)))
sys.exit(1)
return result
def __flatten_json(self, json_obj):
self.collection_name = json_obj[COLLECTION_NAME_KEY]
self.answer = self.__remove_values(json_obj[WHERE_KEY])
if ORDER_KEY in json_obj:
self.answer['ORDER'] = sorted(json_obj[ORDER_KEY])
self.answer_str = json.dumps(self.answer, sort_keys = True)
if __name__ == "__main__":
query = SimpleQueryAST({"where":{"_id":{"$in":["1","2"]},"_rperm":{"$in":["*",null,"xyzzy","spoon"]}}) # just a sample query
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment