Skip to content
On this page

Migration Guide

This guide helps you migrate from other databases to StrataDB.

From MongoDB

If you're currently using MongoDB, StrataDB provides a familiar API with additional type safety benefits.

Key Differences

MongoDBStrataDBNotes
MongoClientStrataMain database class
collection.insertOne()collection.insertOne()Same API
collection.find()collection.find()Same API with type safety
Schema validationSchema definitions with typesCompile-time validation
ObjectIdUUID stringsAuto-generated IDs
Multiple server setupSingle file or in-memorySimpler deployment

Migration Steps

  1. Install StrataDB:
bash
bun add stratadb
  1. Define your document types:
typescript
// MongoDB document
interface UserDocument {
  _id: ObjectId;
  name: string;
  email: string;
  age: number;
}

// StrataDB document
import type { Document } from 'stratadb'

type User = Document<{
  name: string
  email: string
  age: number
}>
  1. Create schemas with indexes:
typescript
// MongoDB: Schema defined in database
// StrataDB: Schema defined in code
import { createSchema } from 'stratadb'

const userSchema = createSchema<User>()
  .field('name', { type: 'TEXT', indexed: true })
  .field('email', { type: 'TEXT', indexed: true, unique: true })
  .field('age', { type: 'INTEGER', indexed: true })
  .build()
  1. Update database connection:
typescript
// ❌ MongoDB approach
import { MongoClient } from 'mongodb'

const client = new MongoClient('mongodb://localhost:27017')
const db = client.db('myapp')
const users = db.collection('users')

// ✅ StrataDB approach
import { Strata } from 'stratadb'

const db = new Strata({ database: 'myapp.db' })
const users = db.collection('users', userSchema)
  1. Update your operations (API is similar):
typescript
// MongoDB and StrataDB have similar APIs
await users.insertOne({ name: 'Alice', email: 'alice@example.com', age: 30 })
await users.find({ age: { $gte: 18 } })

// Note: StrataDB uses simpler APIs - operations work by ID, not filters
await users.updateOne('user-id-here', { name: 'Alice Smith' }) // Update by known ID
await users.deleteOne('user-id-here') // Delete by known ID

Handling MongoDB-Specific Features

ObjectId to UUID Migration

MongoDB uses ObjectId by default, while StrataDB uses UUIDs. If you need to migrate existing ObjectId data:

typescript
type User = Document<{
  originalId?: string  // Store old ObjectId for migration
  name: string
  email: string
}>

// When migrating existing data:
const migrateFromMongo = async () => {
  // Import from MongoDB (pseudo-code)
  const mongoUsers = await mongoUsersCollection.find({}).toArray()
  
  for (const mongoUser of mongoUsers) {
    await stratadbUsers.insertOne({
      originalId: mongoUser._id.toString(),  // Store old ID for reference
      name: mongoUser.name,
      email: mongoUser.email,
    })
  }
}

Aggregation Pipeline Differences

MongoDB has complex aggregation pipelines. StrataDB doesn't support the full pipeline, so you'll need to handle complex operations differently:

typescript
// ❌ MongoDB aggregation
const result = await users.aggregate([
  { $match: { age: { $gte: 18 } } },
  { $group: { _id: '$status', count: { $sum: 1 } } }
]).toArray()

// ✅ StrataDB alternative - simpler queries + application logic
const adults = await users.find({ age: { $gte: 18 } })
const statusCounts = adults.reduce((acc, user) => {
  acc[user.status] = (acc[user.status] || 0) + 1
  return acc
}, {} as Record<string, number>)

Text Search Migration

MongoDB has built-in text search. For similar functionality in StrataDB:

typescript
// MongoDB text search
const results = await users.find({ $text: { $search: 'search term' } })

// ✅ StrataDB alternative - use LIKE or regex with indexed fields
const userSchema = createSchema<User>()
  .field('name', { type: 'TEXT', indexed: true })
  .field('email', { type: 'TEXT', indexed: true })
  .build()

// Then search indexed fields
const results = await users.find({
  $or: [
    { name: { $like: '%search%' } },
    { email: { $like: '%search%' } }
  ]
})

From Prisma/TypeORM

If you're using Prisma or TypeORM, the main difference is that StrataDB is document-oriented rather than relational.

Migration Considerations

Schema Definition

typescript
// Prisma schema.prisma
// model User {
//   id    Int     @id @default(autoincrement())
//   name  String
//   email String  @unique
//   posts Post[]
// }

// ✅ StrataDB approach
type User = Document<{
  name: string
  email: string
  posts?: Post[]  // Embed related data or use references
}>

const userSchema = createSchema<User>()
  .field('name', { type: 'TEXT', indexed: true })
  .field('email', { type: 'TEXT', indexed: true, unique: true })
  .build()

Relationship Handling

typescript
// ❌ Relational approach with joins
const userWithPosts = await prisma.user.findUnique({
  where: { id: 1 },
  include: { posts: true }
})

// ✅ Document approach - either embed or reference
// Option 1: Embed documents
type UserWithPosts = Document<{
  name: string
  email: string
  posts: Post[]  // Embedded in same document
}>

// Option 2: Use references
type User = Document<{
  name: string
  email: string
  postIds: string[]  // References to other documents
}>

From Raw SQLite

If you're currently using raw SQLite with JSON columns, StrataDB provides a structured approach.

Benefits of Migrating from Raw SQLite

  1. Type Safety: Compile-time validation of queries
  2. Simplified Schema Management: Define indexes in code instead of SQL
  3. MongoDB-like API: Familiar interface for document operations
  4. Built-in Validation: Schema validation without extra code

Migration Steps

  1. Analyze your current table structure:
sql
-- Current raw SQLite table
CREATE TABLE users (
  id TEXT PRIMARY KEY,
  data TEXT NOT NULL  -- JSON data
);
  1. Define StrataDB schemas:
typescript
type UserData = {
  name: string
  email: string
  age: number
  metadata: Record<string, unknown>
}

type User = Document<UserData>

const userSchema = createSchema<User>()
  .field('name', { type: 'TEXT', indexed: true })
  .field('email', { type: 'TEXT', indexed: true, unique: true })
  .field('age', { type: 'INTEGER', indexed: true })
  .build()
  1. Migrate existing data:
typescript
// Migration script
const migrateData = async () => {
  // Read from old table
  const oldUsers = db.prepare('SELECT id, data FROM users').all()
  
  for (const oldUser of oldUsers) {
    const userData = JSON.parse(oldUser.data) as UserData
    
    // Insert into new StrataDB collection
    await users.insertOne({
      id: oldUser.id,  // Preserve existing IDs
      ...userData
    })
  }
}
  1. Update your queries:
typescript
// ❌ Raw SQLite with manual JSON extraction
const stmt = db.prepare(`
  SELECT * FROM users 
  WHERE json_extract(data, '$.age') >= ? 
  AND json_extract(data, '$.status') = ?
`)

// ✅ StrataDB with type safety
const adults = await users.find({ 
  age: { $gte: 18 },
  status: 'active'
})

From Other Document Databases

Firebase/Firestore Migration

typescript
// ❌ Firebase approach
import { collection, addDoc, getDocs, query, where } from 'firebase/firestore'

const usersRef = collection(db, 'users')
const userDoc = await addDoc(usersRef, { name: 'Alice', email: 'alice@example.com' })
const adultUsers = await getDocs(query(usersRef, where('age', '>=', 18)))

// ✅ StrataDB approach
const result = await users.insertOne({ name: 'Alice', email: 'alice@example.com', age: 30 })
const adultUsers = await users.find({ age: { $gte: 18 } })

CouchDB/PouchDB Migration

StrataDB doesn't support replication features, so consider this if you rely on synchronization.

Migration Checklist

  • [ ] Update project dependencies (replace old database with StrataDB)
  • [ ] Define TypeScript document types
  • [ ] Create schema definitions with appropriate indexes
  • [ ] Plan data migration strategy
  • [ ] Update connection/setup code
  • [ ] Convert queries to StrataDB syntax (should be similar)
  • [ ] Implement any custom validation logic
  • [ ] Update deployment configuration (no separate database server)
  • [ ] Test all CRUD operations with new type safety
  • [ ] Profile performance to optimize indexes
  • [ ] Update error handling patterns

Handling Common Migration Challenges

Complex Queries

If you have complex SQL-like queries, you may need to handle additional processing in application code:

typescript
// For operations that require complex aggregation
const complexResults = async (minAge: number, minOrderCount: number) => {
  // Find users with criteria
  const users = await db.collection('users', userSchema).find({ age: { $gte: minAge } })
  
  // Apply additional filters in application code
  const results = []
  for (const user of users) {
    const orderCount = await db.collection('orders', orderSchema)
      .count({ userId: user.id })
      
    if (orderCount >= minOrderCount) {
      results.push(user)
    }
  }
  
  return results
}

Database File Management

Unlike MongoDB which runs as a separate service, StrataDB uses files:

typescript
// For production deployment
const db = new Strata({
  database: process.env.NODE_ENV === 'production' 
    ? '/var/lib/myapp/database.db'  // Production path
    : './dev.db'                   // Development path
})

Backup Strategy

Since StrataDB uses a SQLite file, backups are simpler:

bash
# Simple file backup
cp myapp.db myapp.db.backup.$(date +%Y%m%d)

# Or use SQLite's built-in backup command
sqlite3 myapp.db ".backup myapp.db.backup"

By following this guide, you should be able to migrate your existing database to StrataDB while gaining type safety and simpler deployment.

Released under the MIT License.