A clean way to handle MongoDB documents in Pythonic way
Project description
MongoGetterSetter Documentation
MongoGetterSetter is a metaclass that provides a convenient getter and setter API for instances of the classes that use it, allowing natural operations in Python objects to easily reflect in MongoDB documents.
The idea is to convert MongoDB Document into Python Object in High Level, and all other document's sub documents are treated as dictionaties.
This project is under active development.
Usage:
from mongogettersetter import MongoGetterSetter
Methods
-
__getattr__(self, key): Returns aMongoDataWrapperinstance for the givenkey. See below for the capabalities ofMongoDataWrapperExample:
Here, we initialize MyClass with
collectionandfilter_queryas mandatory attributes for MongoGetterSetter to function properly.class MyClass(metaclass=MongoGetterSetter): def init(self, _id): self._id = _id # this ID is used to query self.filter_query = {"id": _id} # or the ObjectID, at your convinence self.collection = collection # Should be a pymongo.MongoClient[database].collection obj = MyClass(_id) result = obj.some_key -
__getitem__(self, key, value): Gets the value of the specifiedkeyfrom the MongoDB document.Example:
print(obj['some_key']) -
__setattr__(self, key, value): Sets the value of the specifiedkeyin the MongoDB document.Example:
obj.some_key = "new_value" -
__setitem__(self, key, value): Sets the value of the specifiedkeyin the MongoDB document.Example:
obj['some_key'] = "new_value" -
__contains__(self, key): Checks if the MongoDB document contains the specifiedkey.Example:
if "some_key" in obj: print("Key exists") -
__str__(self): Returns a string representation of the MongoDB document.Example:
print(obj) -
__delitem__(self, key): Removes the specified key from the MongoDB document.Example:
del obj['some_key'] -
__delattr__(self, key): Removes the specified key from the MongoDB document.Example:
del obj.some_key
MongoDataWrapper
MongoDataWrapper is a class that is also Subscriptable, wraps a MongoDB dococument datatypes and many MongoDB Array Operations to provide a simple, straightforward API to perform various operations on the MongoDB collection.
Methods
-
__init__(self, _id, key, collection): Initialize the instance with the given_id,key, andcollection. -
get(self): Returns the value of the key in the MongoDB document. -
inArray(self, value): Checks if the givenvalueis present in the array of the document's key. -
push(self, *values, maximum=-1): Pushes one or morevaluesinto the array of the document's key. Ifmaximumis specified, it will limit the array size to themaximumvalue. -
addToSet(self, value): Adds avalueto the array of the document's key only if it doesn't exist in the array. -
pop(self, direction=1): Removes the first (direction=-1) or the last (direction=1) element from the array of the document's key. -
pull(self, value): Removes the specifiedvaluefrom the array of the document's key. -
pullAll(self, *values): Removes all occurrences of the specifiedvaluesfrom the array of the document's key. -
size(self, value): Checks if the size of the array of the document's key is equal to the givenvalue. -
elemMatch(self, **kvalues): Checks if the array of the document's key contains at least one element that matches the specified key-value pairs inkvalues. -
all(self, *values): Checks if the array of the document's key contains all the specifiedvalues. -
update(self, field, match, **kvalues): Updates the nested fieldfieldof the document's key where thefieldvalue matchesmatch, with the key-value pairs provided inkvalues. -
__len__(self): Returns the length of the array of the document's key. -
__str__(self): Returns a string representation of the value of the document's key. -
__repr__(self): Returns a string representation of the value of the document's key. -
__del__(self): Deletes the key from the MongoDB document.
MongoDictWrapper
MongoDictWrapper is a class that inherits from the dict class and extends its functionalities. It allows you to access, modify, and manipulate MongoDB documents using Python dictionaries. When a MongoDataWrapper returns a dict, it automatically is wrapped with MongoDictWrapper to allow manipulation of MongoDB object inside a MongoDB object, like a dict inside a dict
Methods
-
__init__(self, *args, **kwargs): Constructor method that initializes the basedictclass. -
prepare(self, _id, key, collection, filter_query): This method initializes the internal data structure that stores information about the document's location in the MongoDB collection. -
__getitem__(self, key): Overrides the basedictmethod to return a wrapped MongoDictWrapper when accessing a nested dictionary. -
__setitem__(self, key, value): Overrides the basedictmethod to update the MongoDB document when setting a key-value pair. -
__delitem__(self, key): Overrides the basedictmethod to delete a key-value pair from the MongoDB document when deleting an item. -
get(self, key, default=None): Overrides the basedictmethod to return the value of the key in the MongoDB document, or thedefaultvalue if the key is not present. -
pop(self, key, default=None): Overrides the basedictmethod to remove and return the value of the key in the MongoDB document, or thedefaultvalue if the key is not present. -
popitem(self): Overrides the basedictmethod to return an arbitrary key-value pair from the MongoDB document. -
setdefault(self, key, default=None): Overrides the basedictmethod to return the value of the key in the MongoDB document if it exists, or sets the key to thedefaultvalue if it does not exist. -
update(self, other): Overrides the basedictmethod to update the MongoDB document with the key-value pairs from theotherdictionary or iterable. -
clear(self): Overrides the basedictmethod to remove all key-value pairs from the MongoDB document. -
__len__(self): Overrides the basedictmethod to return the number of key-value pairs in the MongoDB document. -
__str__(self): Overrides the basedictmethod to return a string representation of the MongoDB document. -
__repr__(self): Overrides the basedictmethod to return a string representation of the MongoDB document.
Examples
To provide a more detailed example, let's assume you have a MongoDB collection named people with the following documents:
[
{
"_id": 1,
"name": "Alice",
"age": 30,
"skills": ["Python", "Django", "JavaScript"],
"contact": {
"email": "alice@example.com",
"phone": "555-1234"
},
"projects": [
{
"title": "Project A",
"status": "completed"
},
{
"title": "Project B",
"status": "in progress"
}
]
},
{
"_id": 2,
"name": "Bob",
"age": 25,
"skills": ["Java", "Spring", "JavaScript"],
"contact": {
"email": "bob@example.com",
"phone": "555-5678"
},
"projects": [
{
"title": "Project X",
"status": "completed"
},
{
"title": "Project Y",
"status": "in progress"
}
]
}
]
Now, let's create a class called People with MongoGetterSetter as its metaclass.
from pymongo import MongoClient
from mongogettersetter import MongoGetterSetter
# Connect to the MongoDB database and collection
client = MongoClient("mongodb://localhost:27017/")
db = client["example_db"]
people_collection = db["people"]
class People(metaclass=MongoGetterSetter):
def __init__(self, _id, collection):
self._id = _id # this ID is used to query
self.filter_query = {"id": _id} # or the ObjectID, at your convenience
self.collection = people_collection # Should be a pymongo.MongoClient[database].collection
# Create a People object for Alice with _id = 1
alice = People(1)
# Access and modify Alice's name
print(alice.name)) # Output: 'Alice'
alice.name = "Alice Johnson"
print(alice.name) # Output: 'Alice Johnson'
# Check if Alice's document has a 'contact' field
if 'contact' in alice:
print("Contact field exists")
# Access and modify Alice's email
print(alice.contact) # Output: {'email': 'alice@example.com', 'phone': '555-1234'}
alice.contact.email = "alice.johnson@example.com"
print(alice.contact.email) # Output: 'alice.johnson@example.com'
# Access and modify Alice's skills
print(alice.skills.get()) # Output: ['Python', 'Django', 'JavaScript']
alice.skills.push("React", maximum=4)
print(alice.skills.get()) # Output: ['Python', 'Django', 'JavaScript', 'React']
alice.skills.pop(direction=-1)
print(alice.skills.get()) # Output: ['Python', 'Django', 'JavaScript']
# Access and modify Alice's projects
print(alice.projects.get()) # Output: [{'title': 'Project A', 'status': 'completed'}, {'title': 'Project B', 'status': 'in progress'}]
alice.projects.update("title", "Project A", status="archived")
print(alice.projects.get()) # Output: [{'title': 'Project A', 'status': 'archived'}, {'title': 'Project B', 'status': 'in progress'}]
More MongoDataWrapper examples
# Create a People object for Alice with _id = 1
alice = People(1)
# Create MongoDataWrapper instances for Alice's skills and projects
alice_skills = alice.skills
alice_projects = alice.projects
# Examples for each method of the MongoDataWrapper class
# 1. get()
print(alice_skills.get()) # Output: ['Python', 'Django', 'JavaScript']
# 2. inArray()
print(alice_skills.inArray("Python")) # Output: True
# 3. push()
alice_skills.push("React", "Java", maximum=5)
print(alice_skills.get()) # Output: ['Python', 'Django', 'JavaScript', 'React', 'Java']
# 4. addToSet()
alice_skills.addToSet("C++")
print(alice_skills.get()) # Output: ['Python', 'Django', 'JavaScript', 'React', 'Java', 'C++']
# 5. pop()
alice_skills.pop(direction=-1)
print(alice_skills.get()) # Output: ['Python', 'Django', 'JavaScript', 'React', 'Java']
# 6. pull()
alice_skills.pull("Java")
print(alice_skills.get()) # Output: ['Python', 'Django', 'JavaScript', 'React']
# 7. pullAll()
alice_skills.pullAll("Python", "React")
print(alice_skills.get()) # Output: ['Django', 'JavaScript']
# 8. size()
print(alice_skills.size(2)) # Output: True
# 9. elemMatch()
print(alice_projects.elemMatch(title="Project A", status="completed")) # Output: True
# 10. all()
print(alice_skills.all("Django", "JavaScript")) # Output: True
# 11. update()
alice_projects.update("title", "Project A", status="archived")
print(alice_projects.get()) # Output: [{'title': 'Project A', 'status': 'archived'}, {'title': 'Project B', 'status': 'in progress'}]
# 12. __len__()
print(len(alice_skills)) # Output: 2
# 13. __str__() and __repr__()
print(alice_skills) # Output: ['Django', 'JavaScript']
print(repr(alice_skills)) # Output: ['Django', 'JavaScript']
More MongoDictWrapper examples
>>> e = Employee(4051)
>>> e
{'_id': ObjectId('640311ab0469a9c4eaf3d2bd'), 'id': 4051, 'name': 'Manoj', 'email': 'manoj123@gmail.com', 'password': 'different password', 'about': None, 'token': '7f471974-ae46-4ac0-a882-1980c300c4d6', 'country': None, 'location': None, 'lng': 0, 'lat': 0, 'dob': None, 'gender': 0, 'userType': 1, 'userStatus': 1, 'profilePicture': 'Images/9b291404-bc2e-4806-88c5-08d29e65a5ad.png', 'coverPicture': 'Images/44af97d9-b8c9-4ec1-a099-010671db25b7.png', 'enablefollowme': False, 'sendmenotifications': False, 'sendTextmessages': False, 'enabletagging': False, 'createdAt': '2020-01-01T11:13:27.1107739', 'updatedAt': '2020-01-02T09:16:49.284864', 'livelng': 77.389849, 'livelat': 28.6282231, 'liveLocation': 'Unnamed Road, Chhijarsi, Sector 63, Noida, Uttar Pradesh 201307, India', 'creditBalance': 127, 'myCash': 0, 'data': [4, 3, 4, 5, 7], 'arr': {'name': 'shiro', 'pass': 'hello', 'score': {'subject': {'minor': 'physics', 'major': 'science'}, 'score': 95}}, 'scores': [{'subject': 'math', 'score': 95}, {'subject': 'physics', 'score': 85}, {'subject': 'chemistry', 'score': 95}], 'recent_views': [4, 4, 4, 4, 4, 4, 4, 4, 4], 'fix': 1, 'hello': 1}
>>> e.arr
{'name': 'shiro', 'pass': 'hello', 'score': {'subject': {'minor': 'physics', 'major': 'science'}, 'score': 95}}
>>> e.arr['name'] = 'sibidharan' # MongoDataWrapper is also Subscriptable
>>> e.arr
{'name': 'sibidharan', 'pass': 'hello', 'score': {'subject': {'minor': 'physics', 'major': 'science'}, 'score': 95}}
>>> e.arr.score # Queried from the MongoDB directly
{'subject': {'minor': 'physics', 'major': 'science'}, 'score': 95}
>>> e.arr.score['subject']
{'minor': 'physics', 'major': 'science'}
>>> e.arr.score['subject']['minor'] = 'chemistry' # All change are reflected in MongoDB Document
>>> e.arr
{'name': 'sibidharan', 'pass': 'hello', 'score': {'subject': {'minor': 'chemistry', 'major': 'science'}, 'score': 95}}
>>> del e.arr.score['subject'] # Can delete any key in dictionary
>>> del e.arr # Can delete a key itself from the MongoDB Document
High-level Overview of the code for contributers to better understand the implementation
Any and all contributions are welcome ❤️
-
MongoDictWrapper: A wrapper for dictionaries that provides additional methods for interaction with MongoDB documents.Methods:
prepare__getitem____setitem____delitem__getpopupdateclear
-
MongoDataWrapper: A wrapper class for the data stored in MongoDB documents.Methods:
getinArraypushaddToSetpoppullpullAllsizeelemMatchallupdate__len____str____repr____getattr____getitem____setattr____setitem____delitem____delattr__
-
MongoGetterSetter: A metaclass that provides a way to override the default behavior ofgetattr,setattr,contains,str,repr, anddelattrto work with MongoDB documents.Nested class:
PyMongoGetterSetterMethods:
__getattr____getitem____setattr____setitem____contains____str____repr____delattr____delitem__
Credits
Thanks to GPT-4 for helping me write this documentation. If you find any errors or somethings doesn't work as the documentation says, raise an issue in here https://git.selfmade.ninja/sibidharan/pymongogettersetter
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file mongogettersetter-1.0.5.tar.gz.
File metadata
- Download URL: mongogettersetter-1.0.5.tar.gz
- Upload date:
- Size: 11.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.10.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8fb655609e9e732b81093e0e3c4e8c113ca4fbf2ac8685380d0981aa0a72f72b
|
|
| MD5 |
5d6ec449d000a2d455495c63d8f258ab
|
|
| BLAKE2b-256 |
a1a01bd10ded1ba95ce58ce9eef32e4372cc8a31c419be2a656f1cf4bd27be3e
|