Document Store
Store structured, JSON-like records inside your Cloud Function's private MongoDB collection.
A Document Store is a database designed to manage data in flexible, self-contained records. Instead of rigid tables with fixed columns, each record can have its own structure. Each Cloud Function has its own private Document Store, backed by a MongoDB collection.
Characteristics
- The store is private to your Cloud Function. No other function can read or write its data.
- The store accepts any JSON-serialisable data.
- A local Document Store is started automatically when you run your function in development.
- In production, data persists until your function deletes it.
- In local development the store resets at every restart of the Ingress. This means that all the data that was uploaded during local testing will be lost. For this reason, it is recommended to only use non-essential test data during local development.
- The store and its available methods require
ixoncdkingress >= 0.0.10to work.
When you start your Cloud Function locally, you should see:
ixoncdkingress - INFO - Starting DocumentDB server
ixoncdkingress - INFO - DocumentDB server started successfullyThese messages confirm the local store is running.
Accessing the Document Store client
The DocumentDBClient is available on the FunctionContext as document_db_client:
from ixoncdkingress.function.context import FunctionContext
@FunctionContext.expose
def document_test(context: FunctionContext):
print(context.document_db_client)
The client can beNoneThe store is not always available. Always check that
context.document_db_clientis notNonebefore using it. Cases where it isNone:
- In development, when calling the function without a company set on the context (a company ID and company name are required for the store to be available).
- When the local MongoDB container fails to boot.
TimezonesAll dates, times, and datetimes are returned as naive objects (no timezone). All values are stored in UTC and should be interpreted as UTC. Always use UTC when storing times.
Document IDs
When you insert a document, the store automatically assigns a BSON ObjectId as _id.
Nested documents and IDs
If needed, like in case of nested documents, you can also create an _id yourself before saving.
Check whether your document is a nested or not: these do not receive an automatic _id. If you need one, assign it yourself with bson.objectid.ObjectId() before saving.
from bson.objectid import ObjectId
_id = ObjectId()
document_to_save = {'_id': _id, 'text': 'test document'}Receiving an _id as a string
_id as a stringThis is the most common cause of find_one or delete_one functions not returning/deleting a document.
If your function receives an _id from the caller as a string (e.g. from a UI Component), you must parse it back to an ObjectId before using it in a filter — otherwise the store will not match the document.
from bson.objectid import ObjectId
@FunctionContext.expose
def remove(context: FunctionContext, note_id: str):
if context.document_db_client:
context.document_db_client.delete_one({'_id': ObjectId(note_id)})Available methods
| Method | Parameters | Description |
|---|---|---|
insert_one | document: Dict | Insert a single document. |
insert_many | documents: Iterable[Dict] | Insert multiple documents. |
update_one | filter_map: Mapping, update: Mapping | Update a single matching document. |
update_many | filter_map: Mapping, update: Mapping | Update all matching documents. |
delete_one | filter_map: Mapping | Delete a single matching document. |
delete_many | filter_map: Mapping | Delete all matching documents. |
find_one | filter_map: Mapping | Return one matching document, or None. |
find | filter_map: Mapping | Return all matching documents. |
Example
Here is a small CRUD pattern over a notes collection, with the matching Svelte UI Component to drive it:
from typing import Any, List, TypedDict
from bson.json_util import dumps
from ixoncdkingress.function.context import FunctionContext
@FunctionContext.expose
def find_text(context: FunctionContext, id: int) -> str | None:
# Find one document by its ID.
# Return None if it doesn't exist, otherwise return its JSON representation.
document = context.document_db_client.find_one(filter_map={'id': id})
if document is None:
return None
return dumps(document)
@FunctionContext.expose
def find_all(context: FunctionContext) -> str:
return dumps(context.document_db_client.find())
@FunctionContext.expose
def add_or_update_text(context: FunctionContext, id: int, text: str) -> None:
# Check whether the document already exists
existing = context.document_db_client.find_one(filter_map={'id': id})
# If the document already exists, update its text;
# otherwise insert a new document.
if existing is not None:
context.document_db_client.update_one({'id': id}, {'$set': {'text': text}})
else:
context.document_db_client.insert_one({'id': id, 'text': text})
class Document(TypedDict):
id: int
text: str
@FunctionContext.expose
def insert_many(context: FunctionContext, documents: List[Document]) -> None:
context.document_db_client.insert_many(documents)<script>
import { onMount } from "svelte";
export let context;
let client;
async function callBackendFunction(functionName, parameters = {}) {
try {
return await client.call(functionName, parameters);
} catch (error) {
console.error(`Error calling ${functionName}:`, error);
}
}
onMount(() => {
client = context.createBackendComponentClient();
(async () => {
await callBackendFunction("functions.notes.find_all");
await callBackendFunction("functions.notes.add_or_update_text", { id: 0, text: "Hello, World!" });
await callBackendFunction("functions.notes.insert_many", {
documents: [{ id: 1, text: "First text" }, { id: 2, text: "Second text" }],
});
})();
});
</script>
<main>
<h1>Frontend Component</h1>
<p>Open the terminal to see the results of the backend calls.</p>
</main>Inspecting the local store
You can browse the contents of your local Document Store with MongoDB Compass or the MongoDB extension for VS Code. This can only be done for a local instance of the Document Store.
For complex queries, see Advanced Document Store Querying.
