Basic MongoDB wrapper for object-oriented collection handling
Project description
Python Basic Utilities - Mongo pbumongo
Available on PyPi
Table of Contents
- Installation
- Usage
- Classes
- AbstractMongoStore - abstract class for handling MongoDB collection access
- MongoConnection - a helper class to assist with creating multiple store instances
- AbstractMongoDocument - abstract class for wrapping MongoDB BSON documents
- AbstractMongoStore - abstract class for handling MongoDB collection access
Installation
Install via pip:
pip install pbumongo
Usage
It is good practice associating a sub-class of AbstractMongoDocument
with a sub-class of AbstractMongoStore
. This is
done through the deserialised_class
parameter in the super()
constructor call of the store class. Any method for
querying documents will use that class to deserialise the BSON document into the provided class, which should extend
AbstractMongoDocument
.
Example: let's say we want to implement access to a collection containing user documents. We'll define a class User
that extends AbstractMongoDocument
and a class UserStore
that extends AbstractMongoStore
.
# main imports
from pbumongo import AbstractMongoDocument, AbstractMongoStore
# supporting imports
import crypt
from typing import List, Optional
from time import time
# this is an example of a minimum viable class
class User(AbstractMongoDocument):
def __init__(self):
super().__init__()
# define attributes with meaningful defaults
self.username: str = None
self.password: str = None
self.permissions: List[str] = []
self.last_login: int = 0
def get_attribute_mapping(self) -> dict:
# the values are what is used inside MongoDB documents
return {
"username": "username",
"password": "password",
"permissions": "permissions",
"last_login": "lastLogin"
}
@staticmethod
def from_json(json: dict):
user = User()
user.extract_system_fields(json)
return user
class UserStore(AbstractMongoStore):
def __init__(self, mongo_url, mongo_db, collection_name):
super().__init__(mongo_url, mongo_db, collection_name, deserialised_class=User, data_model_version=1)
def login(self, username, password) -> Optional[User]:
# encrypt the password!
pw_encrypted = crypt.crypt(password, crypt.METHOD_MD5)
user: Optional[User] = self.query_one({"username": username, "password": pw_encrypted})
if user is not None:
# update last_login attribute and save it in database as well
user.last_login = round(time())
self.update_one(AbstractMongoStore.id_query(user.id),
AbstractMongoStore.set_update("lastLogin", user.last_login))
return user
def create_user(self, username, password) -> User:
# check if this user already exists
existing = self.query_one({"username": username})
if existing is not None:
raise ValueError(f"User with username '{username}' already exists.")
# create new user object
user = User()
user.username = username
user.password = crypt.crypt(password, crypt.METHOD_MD5)
# store in database and return document
user_id = self.create(user)
return self.get(user_id)
MongoConnection
To use these classes in your application, you can use the MongoConnection helper or create the UserStore
class
instance directly. The MongoConnection
helper is useful, when you have a lot of collections and don't want to repeat
the mongo connection URL and DB name for every constructor.
from pbumongo import MongoConnection
from mypackage import UserStore # see implementation above
con = MongoConnection("mongodb://localhost:27017", "myDbName")
user_store = con.create_store(store_class=UserStore, collection_name="users")
user = user_store.login(username="admin", password="mypassword")
Classes
AbstractMongoStore
This is an abstract class and cannot be instantiated directly. Instead, define a class that extends this class.
Constructor
__init__(mongo_url, mongo_db, collection_name, deserialised_class, data_model_version=1)
mongo_url
- this is the Mongo connection URL containing the host, port and optional username, passwordmongo_db
- this is the Mongo DB name - the one you provide when usinguse <dbname>
on the Mongo shellcollection_name
- the name of the collection - e.g.myCollection
fordb.myCollection.find({})
on the Mongo shelldeserialised_class
- used for all the query methods to deserialise the BSON document into a class with attributes for easier accessdata_model_version
- a number that can be used for database migration as an app develops over time
Methods
get(doc_id: str)
- fetches a single document with a matchingdoc_id == document["_id"]
get_all()
- fetches the entire collection content and deserialises every document. Careful, this is not an iterator, but returns alist
of all the documents and can consume quite a bit of compute and memory.create(document)
- creates a new document and returns the_id
of the newly created BSON document as string. Thedocument
can be eitherdict
or an instance of thedeserialised_class
provided in thesuper().__init(..)
call.- Since version 1.0.1 a new parameter is available
create(document, return_doc=True)
which will return the entire document/object instead of just the_id
of the newly created document.
- Since version 1.0.1 a new parameter is available
query_one(query: dict)
- fetches a single document and deserialises it or returnsNone
if no document can be foundquery(query: dict, sorting, paging)
- fetches multiple documents and deserialises them.sorting
can be an attribute name (as provided in the BSON) or a dictionary with the sort order.paging
is an instance ofpbumongo.PagingInformation
.update_one(query: dict, update: dict)
- proxies thedb.collection.updateOne(..)
function from the Mongo shellupdate(query:, update: dict
- same asupdate_one
, but will update multiple documents, if the query matchesupdate_full(document)
- shortcut for updating the entire document with an updated version, the query will be constructed from theid
/_id
provided by thedocument
.delete(doc_id)
- deletes a single document with the provided document IDdelete_many(query: dict)
- deletes multiple documents matching the query.
Static Methods
AbstractMongoStore.id_query(string_id: str)
- creates a query{ "_id": ObjectId(string_id) }
, which can be used to query the databaseAbstractMongoStore.set_update(keys, values)
- creates a$set
update statement. If only a single attribute is updated, you can pass them directly as parameters, e.g. updating a key"checked": True
, can be done by.set_update("checked", True)
. If you update multiple attributes provide them as list in the matching order.AbstractMongoStore.unset_update(keys)
- creates an$unset
update statement with the attributes listed askeys
. Similarly to.set_update
, you can provide a single key without a list for ease of use.
AbstractMongoDocument
This is an abstract class and cannot be instantiated directly. Instead, define a class that extends this class.
Constructor
__init__(doc_id=None, data_model_version=None)
The parameters are entirely optional. Generally it is recommended to use the static method from_json(json: dict)
to
create BSON documents you've loaded from the database instead of calling the constructor. For new documents, you would
not provide the _id
as the store class handles that.
Methods
For methods and static methods please see the documentation of JsonDocument
from pbu
. AbstractMongoDocument
extends that class.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file pbumongo-1.1.2.tar.gz
.
File metadata
- Download URL: pbumongo-1.1.2.tar.gz
- Upload date:
- Size: 14.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.5
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0770df6362306a833422aa9bbafbb56517c8dcbe679219cd6779f31362af706d |
|
MD5 | 3e13ebd59ac63357516191133b5fc35b |
|
BLAKE2b-256 | dc47302fa4953c405d97d48dd451c49762c43ec74054844cd2394b4de56b520d |
File details
Details for the file pbumongo-1.1.2-py3-none-any.whl
.
File metadata
- Download URL: pbumongo-1.1.2-py3-none-any.whl
- Upload date:
- Size: 13.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.5
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | a5f2d44dea2826c46dbbe2834ad161fe3dc5ed7b24334443a2aad686512e711c |
|
MD5 | b65be6588e0657892a83ef8d0d3b497f |
|
BLAKE2b-256 | 6ca5bbf6330fdc5de51fe7443140c181ccf27bfb7d1637067775132c67339df2 |