/ˈmɑːŋɡoʊ kiː ˈvæljuː/

Tiny async/sync key–value store on top of PyMongo.

Harrison Erd · BSD 3-Clause

User Guide

mongoKV is a tiny key–value store wrapper around MongoDB using PyMongo.

Think of it as MongoDB as a dict instead of a database, for lazy programmers who just want to save some simple data.

Installation

pip install mongokv

You’ll also need a running MongoDB instance and a valid connection URI, for example:

mongodb://localhost:27017

Check out An Introduction to MongoDB Connection Strings for help on getting a MongoDB instance up and running. A super easy way to do this is to use Atlas, that way your instance is in the cloud and you won't need a Mongo server running on your local device.

Core Concepts

Each key is stored as a single MongoDB document:

{
  "_id": "<str(key)>",
  "value": <your_data>
}

Same methods, two modes. Start simple, grow into MongoDB when you need more.

Quickstart

Synchronous usage

from mongokv import Mkv

db = Mkv("mongodb://localhost:27017")

# Set a value with an explicit key
db.set("username", "harrison")

# Get it back
print(db.get("username"))  # -> "harrison"

# Set a value with an auto-generated key
note_id = db.set(None, {"title": "mongoKV", "tags": ["mongo", "kv"]})
print(note_id)  # -> e.g. "677eec65e92eeca23513fe99"

# List all keys
print(db.all())  # -> ["username", "677eec65e92eeca23513fe99", ...]

# Remove a key
db.remove("username")

# Clear everything
db.purge()

# Close connections when you’re done
db.close()

Asynchronous usage

import asyncio
from mongokv import Mkv

db = Mkv("mongodb://localhost:27017")

async def main():
    # Set a value with explicit key
    await db.set("counter", 1)

    # Increment and save again
    current = await db.get("counter", 0)
    await db.set("counter", current + 1)

    # Auto-generated key
    new_id = await db.set(None, {"hello": "world"})
    print("New id:", new_id)

    # List all keys
    keys = await db.all()
    print("Keys:", keys)

    # Remove key
    deleted = await db.remove("counter")
    print("Deleted:", deleted)

    # Purge all keys
    await db.purge()

    # Close connections
    await db.close()

asyncio.run(main())

API Reference

class Mkv

Create a new mongoKV instance.

Parameters

Internally it maintains:

These are used automatically based on sync/async context.

set

Set a value for a given key. If key is None, a new ObjectId-based key will be generated.

Behavior

Parameters

Returns

str: The key used for this record.

Examples (sync)

db.set("user:1", {"name": "Alice"})
auto_id = db.set(None, {"name": "Bob"})

Examples (async)

key = await db.set("session:123", {"state": "active"})
new_id = await db.set(None, {"foo": "bar"})

get

Fetch the value for a given key.

Behavior

Parameters

Returns

The stored value. If the key is missing, returns default if provided, otherwise raises KeyError.

Examples (sync)

# strict (dict-like)
try:
    user = db.get("user:1")
except KeyError:
    user = None

# fallback behavior
user = db.get("user:1", default={})
missing = db.get("nope", default="N/A")   # -> "N/A"
none_ok = db.get("nope", default=None)    # -> None

Examples (async)

# strict (dict-like)
try:
    user = await db.get("user:1")
except KeyError:
    user = None

# fallback behavior
user = await db.get("user:1", default={})
none_ok = await db.get("nope", default=None)

remove

Delete a single document by key.

Behavior

Parameters

Returns

bool: True if a document was deleted, False otherwise.

Examples (sync)

deleted = db.remove("user:1")
if deleted:
    print("User removed")

Examples (async)

deleted = await db.remove("user:1")

all

List all keys (all _id values) in the collection.

Behavior

Returns

list[str]: All keys currently stored.

Examples (sync)

keys = db.all()
print(keys)  # -> ["user:1", "note:abc", ...]

Examples (async)

keys = await db.all()

purge

Delete all documents in the collection. Use with care.

Behavior

Returns

bool: Always True if no exception is raised.

Examples (sync)

db.purge()  # All keys gone

Examples (async)

await db.purge()

close

Close both the async and sync MongoDB clients.

Behavior

Returns

None

Examples (sync)

db.close()

Examples (async)

await db.close()

Closing is optional in short-lived scripts, but recommended in long-running apps and tests.

When is it sync vs async?

The library uses:

def in_async() -> bool:
    try:
        asyncio.get_running_loop()
        return True
    except RuntimeError:
        return False

Error Handling

The current implementation doesn’t wrap MongoDB errors – any connection or operation issue will bubble up as a PyMongo/AsyncMongo exception. Typical things you might see:

You can catch them at the call site:

from pymongo.errors import PyMongoError

try:
    db.set("x", object())
except PyMongoError as e:
    print("Mongo blew up:", e)