mongo/README.md
disqualifier 9ad3458cf9 fix: align push helpers to matched_count for success-contract consistency (v0.1.3)
mongo-1: document_push_array and document_push_and_set still returned modified_count>0
while the v0.1.2 wave moved the sibling single-doc update helpers to matched_count>0.
$push always mutates so the two agree in practice (no reachable behavioral change), but
the helpers now match the documented 'True when a document matched' contract uniformly.

sibling-grep: zero consumers of either push helper.
Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-29 20:48:08 -04:00

76 lines
2.4 KiB
Markdown

# mongo
Async MongoDB wrapper over [motor](https://motor.readthedocs.io/). Thin, opinionated
helpers for the common paths, with a raw escape hatch for everything else.
## Install
`requirements.txt`:
```
mongo @ git+ssh://git@git.rethinkstudios.io/rethink-public/mongo.git@v0.1.3
```
Direct:
```bash
pip install "mongo @ git+ssh://git@git.rethinkstudios.io/rethink-public/mongo.git@v0.1.3"
```
Requires `motor` and `pymongo` (pulled transitively).
Drop the `@v0.1.3` suffix from the line above to install the latest unpinned.
## Usage
**Object (preferred)** — one client per process:
```python
from mongo import Mongo
db = Mongo(conn_string, database) # attach as bot.db / app.db
users = await db.get_documents("users", {"active": True})
db.close() # on shutdown (sync)
```
**Module proxy (back-compat)** — arm once, then call bare:
```python
import mongo # NOT `from mongo import ...`
mongo.init(conn_string, database)
users = await mongo.get_documents("users", {"active": True})
```
Both styles share one client. The proxy exists so legacy call sites keep working
after a one-line `init()`; new code should use the object.
## Error contract
- **Wrapped methods** log-and-swallow exceptions and return a safe default
(`False` / `[]` / `{}` / `0` / `None`). Branch on the result.
- **`db.collection(name)`** (or `db[name]`) returns the raw motor collection:
full driver surface, no swallowing, **raises**. Use it for anything not wrapped
(`find_one_and_*` beyond what's exposed, change streams, complex bulk ops).
## API
See the module docstring and method docstrings in `mongo.py` — that's the source
of truth. Grouped as: collection/index management, create, read, update, delete,
bulk, checks. Atomic ops (`find_one_and_update/replace/delete`) and `bulk_write`
are included.
## Gotchas
- `from mongo import func` won't see the proxy (resolved at import, before `init`).
Use `import mongo` then `mongo.func(...)`.
- `find_one_and_update` returns the **after** image by default (`return_after=True`).
- `bulk_write` takes pymongo ops the caller builds:
```python
from pymongo import UpdateOne
ops = [UpdateOne({"_id": i}, {"$set": {...}}, upsert=True) for i in ids]
await db.bulk_write("col", ops)
```
## Versioning
Releases are tagged `vX.Y.Z`. The install line above pins a release; drop the `@vX.Y.Z` suffix to install the latest unpinned. Pin deliberately for reproducible installs.