MongoStorage
extends BaseStorage
in package
MongoDB-backed FSM storage.
Mirrors aiogram.fsm.storage.mongo.MongoStorage (≈170 lines).
State and data are stored as fields inside a single MongoDB document
keyed by _id = keyBuilder->build($key) (no part suffix — one document
per FSM context, unlike Redis which uses separate keys per part).
I/O model
The mongodb/mongodb userland library is synchronous (blocking I/O).
Every blocking call is wrapped in Amp\async(fn) so the blocking work
runs in a separate fiber and the parent fiber is suspended, not stalled.
This mirrors the pattern established in BaseSession.
Dependency injection
The constructor accepts a MongoCollectionInterface — a tiny internal
contract satisfied by MongoCollectionAdapter (which wraps the real
\MongoDB\Collection) in production, and by lightweight anonymous-class
mocks in unit tests. This decouples the storage from ext-mongodb at
the type level, so the unit-test suite runs without the extension.
Factory methods
MongoStorage::fromUrl(string $url, ...)— builds a real\MongoDB\Client, wraps the selected collection in an adapter. Requiresext-mongodb.MongoStorage::create(\MongoDB\Client $client, ...)— same but accepts a pre-built client (useful when TLS / auth options are complex).MongoStorage::fromCollection(MongoCollectionInterface $col, ...)— primary injection point; used by unit tests.
Document structure
{ "_id": "<keyBuilder_output>", "state": "Group:name", "data": { ... } }
When state / data is cleared, $unset removes the field. If both
fields are absent after the update the document is deleted to avoid
accumulating empty records (upstream Python behaviour).
Tags
Table of Contents
Properties
Methods
- __construct() : mixed
- close() : void
- Release resources.
- create() : self
- Create a `MongoStorage` from an existing `\MongoDB\Client`.
- fromCollection() : self
- Create a `MongoStorage` from a `MongoCollectionInterface` directly.
- fromUrl() : self
- Create a `MongoStorage` from a MongoDB connection URI.
- getData() : array<string, mixed>
- Retrieve the FSM data payload for the given key.
- getState() : null|string
- Retrieve the FSM state for the given key.
- getValue() : mixed
- Read a single key from the data map stored at `$storageKey`.
- setData() : void
- Persist the FSM data payload for the given key.
- setState() : void
- Persist the FSM state for the given key.
- updateData() : array<string, mixed>
- Merge `$data` into the existing FSM data payload for `$key` atomically.
- unsetField() : void
- Remove `$field` from the document identified by `$documentId` using `$unset`. If the document is empty after the update (or absent), the whole document is deleted to avoid accumulating empty records.
Properties
$collection read-only
private
MongoCollectionInterface
$collection
$keyBuilder read-only
private
KeyBuilder
$keyBuilder
= new DefaultKeyBuilder()
Methods
__construct()
public
__construct(MongoCollectionInterface $collection[, KeyBuilder $keyBuilder = new DefaultKeyBuilder() ]) : mixed
Parameters
- $collection : MongoCollectionInterface
-
Adapted MongoDB collection.
- $keyBuilder : KeyBuilder = new DefaultKeyBuilder()
-
Key-builder strategy.
close()
Release resources.
public
close() : void
\MongoDB\Client manages an internal connection pool and does not
expose an explicit close() method. This is intentionally a no-op,
matching upstream Python's self._client.close() which is also
effectively a no-op in most deployments.
create()
Create a `MongoStorage` from an existing `\MongoDB\Client`.
public
static create(Client $client[, string $database = 'phpbotgram_fsm' ][, string $collectionName = 'states_and_data' ][, null|KeyBuilder $keyBuilder = null ]) : self
Parameters
- $client : Client
-
Pre-built MongoDB client.
- $database : string = 'phpbotgram_fsm'
-
Database name.
- $collectionName : string = 'states_and_data'
-
Collection name.
- $keyBuilder : null|KeyBuilder = null
-
Optional key-builder override.
Return values
selffromCollection()
Create a `MongoStorage` from a `MongoCollectionInterface` directly.
public
static fromCollection(MongoCollectionInterface $collection[, null|KeyBuilder $keyBuilder = null ]) : self
This is the primary injection point used by unit tests.
Parameters
- $collection : MongoCollectionInterface
-
Adapted (or mocked) collection.
- $keyBuilder : null|KeyBuilder = null
-
Optional key-builder override.
Return values
selffromUrl()
Create a `MongoStorage` from a MongoDB connection URI.
public
static fromUrl(string $url[, array<string, mixed> $clientOptions = [] ][, array<string, mixed> $driverOptions = [] ][, string $database = 'phpbotgram_fsm' ][, string $collectionName = 'states_and_data' ][, null|KeyBuilder $keyBuilder = null ]) : self
Mirrors MongoStorage.from_url (upstream Python). Requires ext-mongodb.
Parameters
- $url : string
-
MongoDB connection URI.
- $clientOptions : array<string, mixed> = []
-
Options forwarded to
\MongoDB\Client. - $driverOptions : array<string, mixed> = []
-
Driver options forwarded to
\MongoDB\Client. - $database : string = 'phpbotgram_fsm'
-
Database name.
- $collectionName : string = 'states_and_data'
-
Collection name.
- $keyBuilder : null|KeyBuilder = null
-
Optional key-builder override.
Return values
selfgetData()
Retrieve the FSM data payload for the given key.
public
getData(StorageKey $key) : array<string, mixed>
Parameters
- $key : StorageKey
-
Storage address.
Return values
array<string, mixed> —Current data map (empty array when no data stored).
getState()
Retrieve the FSM state for the given key.
public
getState(StorageKey $key) : null|string
Parameters
- $key : StorageKey
-
Storage address.
Return values
null|string —Stored state name, or null if none.
getValue()
Read a single key from the data map stored at `$storageKey`.
public
getValue(StorageKey $storageKey, string $dictKey[, mixed $default = null ]) : mixed
Returns $default when the dict key is absent. PHP collapses the
upstream @overload pattern into one method with a mixed $default = null
parameter.
Parameters
- $storageKey : StorageKey
-
Storage address.
- $dictKey : string
-
Key within the data map.
- $default : mixed = null
-
Value to return when
$dictKeyis not present.
Return values
mixed —The stored value, or $default.
Mirrors BaseStorage.get_value (base.py:151-168).
setData()
Persist the FSM data payload for the given key.
public
setData(StorageKey $key, array<string, mixed> $data) : void
An empty array results in the data field being $unset. If the
document becomes entirely empty afterward it is deleted.
Parameters
- $key : StorageKey
-
Storage address.
- $data : array<string, mixed>
-
Data map to store.
setState()
Persist the FSM state for the given key.
public
setState(StorageKey $key[, null|State|string $state = null ]) : void
$state === null→$unsetthestatefield; if the document is now empty (nodatafield either), delete the document.$state instanceof State→ store$state->state().$stateis a plain string → store as-is.
Every blocking MongoDB call is wrapped in Amp\async() so the
event loop is not stalled.
Parameters
- $key : StorageKey
-
Storage address.
- $state : null|State|string = null
-
New state value.
updateData()
Merge `$data` into the existing FSM data payload for `$key` atomically.
public
updateData(StorageKey $key, array<string, mixed> $data) : array<string, mixed>
Unlike the default BaseStorage::updateData (read-merge-write, racy
under concurrency), this override uses a single updateOne with
dot-notation $set — matching upstream's atomic
findOneAndUpdate($set: {data.field: value, ...}, upsert=True) pattern
(aiogram/fsm/storage/mongo.py:133-146).
When $data is empty the operation is skipped and the current data is
returned unchanged.
Parameters
- $key : StorageKey
-
Storage address.
- $data : array<string, mixed>
-
Partial data map to merge in.
Return values
array<string, mixed> —The merged data map as it now exists in the document.
unsetField()
Remove `$field` from the document identified by `$documentId` using `$unset`. If the document is empty after the update (or absent), the whole document is deleted to avoid accumulating empty records.
private
unsetField(string $documentId, string $field) : void
Must be called from within an Amp\async() closure.
Parameters
- $documentId : string
- $field : string