-
-
Save aficionado/aba65cd754bceeba5739 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from pymongo.son_manipulator import SONManipulator | |
class KeyTransform(SONManipulator): | |
"""Transforms keys going to database and restores them coming out. | |
This allows keys with dots in them to be used (but does break searching on | |
them unless the find command also uses the transform. | |
Example & test: | |
# To allow `.` (dots) in keys | |
import pymongo | |
client = pymongo.MongoClient("mongodb://localhost") | |
db = client['delete_me'] | |
db.add_son_manipulator(KeyTransform(".", "_dot_")) | |
db['mycol'].remove() | |
db['mycol'].update({'_id': 1}, {'127.0.0.1': 'localhost'}, upsert=True, | |
manipulate=True) | |
print db['mycol'].find().next() | |
print db['mycol'].find({'127_dot_0_dot_0_dot_1': 'localhost'}).next() | |
Note: transformation could be easily extended to be more complex. | |
""" | |
def __init__(self, replace, replacement): | |
self.replace = replace | |
self.replacement = replacement | |
def transform_key(self, key): | |
"""Transform key for saving to database.""" | |
return key.replace(self.replace, self.replacement) | |
def revert_key(self, key): | |
"""Restore transformed key returning from database.""" | |
return key.replace(self.replacement, self.replace) | |
def transform_incoming(self, son, collection): | |
"""Recursively replace all keys that need transforming.""" | |
for (key, value) in son.items(): | |
if self.replace in key: | |
if isinstance(value, dict): | |
son[self.transform_key(key)] = self.transform_incoming( | |
son.pop(key), collection) | |
else: | |
son[self.transform_key(key)] = son.pop(key) | |
elif isinstance(value, dict): # recurse into sub-docs | |
son[key] = self.transform_incoming(value, collection) | |
return son | |
def transform_outgoing(self, son, collection): | |
"""Recursively restore all transformed keys.""" | |
for (key, value) in son.items(): | |
if self.replacement in key: | |
if isinstance(value, dict): | |
son[self.revert_key(key)] = self.transform_outgoing( | |
son.pop(key), collection) | |
else: | |
son[self.revert_key(key)] = son.pop(key) | |
elif isinstance(value, dict): # recurse into sub-docs | |
son[key] = self.transform_outgoing(value, collection) | |
return son |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment