LioranDB TypeScript Series #4: Type-Safe CRUD with Databases and Collections
LioranDB TypeScript Series: Build with a developer-first document database powered by Rust and designed for TypeScript.
We have a connection.
Now let's store actual application data.
Define your model
type Product = {
_id?: string;
sku: string;
title: string;
price: number;
inStock: boolean;
category: string;
};
Then create a typed collection:
const db = client.db("default");
const products =
db.collection<Product>("products");
Now your application gets TypeScript assistance when working with documents.
Insert one document
const result = await products.insertOne({
sku: "bk-001",
title: "Blue Notebook",
price: 149,
inStock: true,
category: "stationery",
});
console.log(result.insertedId);
Insert multiple documents
await products.insertMany([
{
sku: "bk-002",
title: "Black Notebook",
price: 199,
inStock: true,
category: "stationery",
},
{
sku: "pn-001",
title: "Marker",
price: 49,
inStock: true,
category: "writing",
},
]);
Find documents
const available = await products
.find({ inStock: true })
.sort({ price: 1 })
.limit(10)
.toArray();
Find one:
const product = await products.findOne({
sku: "bk-001",
});
Count documents:
const total = await products.countDocuments();
const availableCount =
await products.countDocuments({
inStock: true,
});
Update documents
await products.updateOne(
{ sku: "bk-001" },
{
$set: {
inStock: false,
},
}
);
Or update multiple:
await products.updateMany(
{ category: "stationery" },
{
$set: {
inStock: true,
},
}
);
Delete documents
await products.deleteOne({
sku: "bk-001",
});
Or:
await products.deleteMany({
category: "discontinued",
});
Query operators
Filters can go beyond equality.
const productsOver100 = await products
.find({
price: {
$gte: 100,
},
})
.toArray();
Text queries are also available when the corresponding text index exists:
const matches = await products.find({
$text: {
$search: "Notebook",
$field: "title",
},
}).toArray();
We'll explore that properly in the next two articles.
Idempotency keys
For write operations where retry safety matters, you can provide an idempotency key:
await products.insertOne(
{
sku: "bk-100",
title: "Engineering Notebook",
price: 299,
inStock: true,
category: "stationery",
},
{
idempotencyKey: "product-bk-100-create",
}
);
This is especially useful around network retries and application workflows where accidentally performing the same logical write twice would be painful.
Database operations
The database handle itself supports operations such as:
db.collection("products");
await db.createCollection("events");
await db.listCollections();
await db.dropCollection("old-data");
And when you really mean it:
await db.dropDatabase();
Maybe don't put that last one behind a giant red button called "probably fine". ðŸ˜
Resources
Database & Collections Docs:
https://docs.liorandb.com/docs/driver/database-and-collections
Documentation: https://docs.liorandb.com
Website: https://liorandb.com
Creator: https://github.com/UltronTheAI
Previous: Part 3 → Connections & Lifecycle
Next: Part 5 → FindCursor, Query Shaping & Text Search
Top comments (0)