Skip to content

danielxceron/docudb

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

28 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DocuDB

npm version

Overview

DocuDB is a lightweight, document-based NoSQL database for Node.js applications. It provides a MongoDB-like interface with zero external dependencies, making it perfect for small to medium-sized projects or environments where a full database installation is not feasible.

Features

  • Document-Based Storage: Store and retrieve JSON documents with automatic ID generation
  • Schema Validation: Define schemas to validate document structure and data types
  • Indexing: Create and manage indexes for faster queries
  • Query System: Powerful query capabilities with MongoDB-like syntax
  • Compression: Optional gzip compression to reduce storage size
  • Chunking: Efficient handling of large documents through chunking
  • UUID Support: Choose between MongoDB-style IDs or UUID v4 format
  • Custom Default Functions: Define dynamic default values using custom functions
  • TypeScript Support: Full TypeScript definitions for enhanced developer experience
  • Zero Dependencies: No external runtime dependencies

Installation

npm install docudb

Basic Usage

import { Database, Schema } from 'docudb';

// Initialize database
const db = new Database({ 
  name: 'myDatabase',
  compression: true
});

await db.initialize();

// Create a collection with schema
const userSchema = new Schema({
  name: { type: 'string', required: true },
  email: { type: 'string', required: true },
  age: { type: 'number', default: 0 },
  createdAt: { type: 'date', default: () => new Date() }
});

const users = db.collection('users', { schema: userSchema });

// Insert a document
const user = await users.insertOne({
  name: 'John Doe',
  email: 'john@example.com',
  age: 30
});

console.log('Inserted user:', user);

// Query documents
const results = await users.find({ age: { $gt: 25 } });
console.log('Users over 25:', results);

// Update a document
const updated = await users.updateById(user._id, {
  $set: { age: 31 }
});

// Delete a document
await users.deleteById(user._id);

Configuration Options

Database Options

const db = new Database({
  name: 'myDatabase',       // Database name (default: 'docudb')
  dataDir: './data',        // Data directory (default: './data')
  chunkSize: 2 * 1024 * 1024, // Chunk size in bytes (default: 1MB)
  compression: true,        // Enable compression (default: true)
  idType: 'uuid'            // ID generation type: 'mongo' or 'uuid' (default: 'mongo')
});

Collection Options

const collection = db.collection('myCollection', {
  schema: mySchema,         // Schema for validation
  idType: 'uuid',           // Override database ID type
  timestamps: true          // Add createdAt and updatedAt fields automatically
});

Schema Validation

DocuDB supports schema validation to ensure data integrity:

const productSchema = new Schema({
  name: { 
    type: 'string', 
    required: true,
    validate: { minLength: 3 }
  },
  price: { 
    type: 'number', 
    required: true,
    validate: { min: 0 }
  },
  tags: { 
    type: 'array', 
    default: [] 
  },
  inStock: { 
    type: 'boolean', 
    default: true 
  },
  metadata: { 
    type: 'object', 
    default: {} 
  }
});

Pattern Validation

You can use regular expressions to validate string formats:

const userSchema = new Schema({
  email: {
    type: 'string',
    required: true,
    validate: {
      pattern: /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/,
      message: 'Invalid email format'
    }
  },
  phone: {
    type: 'string',
    validate: {
      pattern: /^\+?[1-9]\d{1,14}$/,  // E.164 format
      message: 'Phone number must be in international format'
    }
  },
  username: {
    type: 'string',
    required: true,
    validate: {
      pattern: /^[a-z0-9_-]{3,16}$/,
      message: 'Username must be 3-16 characters and contain only letters, numbers, underscores or hyphens'
    }
  },
  productCode: {
    type: 'string',
    validate: {
      // Custom product code format: ABC-12345
      pattern: /^[A-Z]{3}-\d{5}$/,
      message: 'Product code must be in format: ABC-12345'
    }
  }
});

// Combining pattern validation with other validations
const advancedSchema = new Schema({
  url: {
    type: 'string',
    validate: {
      pattern: /^https?:\/\/[\w\.-]+\.[a-z]{2,}\/?.*$/,
      minLength: 10,
      maxLength: 2048,
      message: 'Invalid URL format'
    }
  },
  zipCode: {
    type: 'string',
    validate: {
      // Support multiple country formats with conditional validation
      custom: (value, doc) => {
        if (doc.country === 'US') {
          return /^\d{5}(-\d{4})?$/.test(value) || 'Invalid US zip code';
        } else if (doc.country === 'CA') {
          return /^[A-Za-z]\d[A-Za-z] ?\d[A-Za-z]\d$/.test(value) || 'Invalid Canadian postal code';
        }
        return true;
      }
    }
  }
});

Custom Default Functions

You can define dynamic default values using custom functions:

const schema = new Schema({
  createdAt: {
    type: 'date',
    default: () => new Date()
  },
  code: {
    type: 'string',
    // Generate a code based on the document
    default: (doc) => `PROD-${doc.name.substring(0, 3).toUpperCase()}-${Math.floor(Math.random() * 1000)}`
  }
});

UUID Support

DocuDB supports both MongoDB-style IDs and UUID v4 format:

// Collection with UUID IDs
const products = db.collection('products', { idType: 'uuid' });

// Insert a document (will have UUID v4 _id)
const product = await products.insertOne({
  name: 'Laptop',
  price: 999
});

// You can also provide your own UUID
const customProduct = await products.insertOne({
  _id: '123e4567-e89b-42d3-a456-556642440000', // Valid UUID v4
  name: 'Custom ID Product',
  price: 599
});

Query Operations

DocuDB supports MongoDB-like query operations:

// Find all documents
const allProducts = await products.find({});

// Find with conditions
const expensiveProducts = await products.find({ 
  price: { $gt: 500 },
  inStock: true
});

// Find one document
const laptop = await products.findOne({ name: 'Laptop' });

// Find by ID
const product = await products.findById('123e4567-e89b-42d3-a456-556642440000');

// Count documents
const count = await products.count({ price: { $lt: 100 } });

Update Operations

// Update by ID
const updated = await products.updateById(productId, {
  $set: { price: 899, inStock: false }
});

// Update one document
const result = await products.updateOne(
  { name: 'Laptop' },
  { $inc: { stock: -1 } }
);

// Update many documents
const result = await products.updateMany(
  { category: 'Electronics' },
  { $set: { discount: 10 } }
);

Delete Operations

DocuDB provides several methods for deleting documents from your collections. This section covers all available delete operations with practical examples.

Available Delete Methods

deleteById(id) deleteOne(filter) deleteMany(filter)

// Insert a document first
const product = await products.insertOne({
  name: 'Headphones',
  price: 50,
  stock: 10
});

// Delete the document by its ID
const deleted = await products.deleteById(product._id);
console.log(deleted); // true

// Verify deletion
const found = await products.findById(product._id);
console.log(found); // null

await products.insertMany([
  { name: 'Mouse', price: 20, stock: 10 },
  { name: 'Keyboard', price: 50, stock: 8 },
  { name: 'Monitor', price: 150, stock: 3 }
]);

// Delete the first document matching the criteria
const deleted = await products.deleteOne({ name: 'Mouse' });
console.log(deleted); // true

// Check remaining count
const count = await products.count();
console.log(count); // 2 (only Mouse was deleted)

// Delete all products with price >= 50
const deletedCount = await products.deleteMany({ 
  price: { $gte: 50 } 
});
console.log(deletedCount); // 2 (Keyboard, Monitor)

Indexing

Create indexes to improve query performance:

// Create a simple index
await products.createIndex('name');

// Create a unique index
await products.createIndex('name', { unique: true });

// Create a compound index
await products.createIndex(['category', 'brand'], { 
  name: 'category_brand_idx'
});

Error Handling

DocuDB provides detailed error information:

try {
  await products.insertOne({
    name: 'Invalid Product',
    price: 'not-a-number' // Schema violation
  });
} catch (error) {
  if (error.code === 'SCHEMA_VALIDATION_ERROR') {
    console.error('Validation error:', error.details);
  } else {
    console.error('Database error:', error.message);
  }
}

License

MIT

About

Document-based NoSQL database for NodeJS

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors