@andrejs1979/document
Version:
MongoDB-compatible document database for NoSQL
455 lines • 16 kB
JavaScript
/**
* NoSQL - Main Document Database Class
* MongoDB-compatible document database with vector integration
*/
import { DocumentError } from './types';
import { DocumentStorage } from './storage/document-storage';
import { MongoQueryEngine } from './operations/query-engine';
import { DocumentIndexManager } from './indexes/index-manager';
import { RelationshipManager } from './relationships/relationship-manager';
import { HybridSearchEngine } from './operations/hybrid-search';
import { BulkOperationsManager } from './operations/bulk-operations';
import { TaggingSystem } from './metadata/tagging-system';
/**
* Main NoSQL Document Database class
*/
export class EdgeDocumentDB {
storage;
queryEngine;
indexManager;
relationshipManager;
hybridSearchEngine;
bulkOperationsManager;
taggingSystem;
config;
initialized = false;
constructor(config) {
this.config = config;
this.storage = new DocumentStorage(config);
this.indexManager = new DocumentIndexManager(config);
this.queryEngine = new MongoQueryEngine(config.d1Database, this.indexManager);
this.relationshipManager = new RelationshipManager(this.storage, config);
this.hybridSearchEngine = new HybridSearchEngine(this.storage, this.queryEngine, config);
this.bulkOperationsManager = new BulkOperationsManager(this.storage, config);
this.taggingSystem = new TaggingSystem(this.storage, config);
}
/**
* Initialize the document database
*/
async initialize() {
if (this.initialized)
return;
try {
await this.storage.initialize();
this.initialized = true;
console.log(`EdgeDocumentDB initialized: ${this.config.name}`);
}
catch (error) {
throw new DocumentError(`Database initialization failed: ${error.message}`, 'INIT_ERROR');
}
}
// ===============================
// Core CRUD Operations
// ===============================
/**
* Insert a single document
*/
async insertOne(collection, document) {
await this.ensureInitialized();
// Auto-tag if enabled
if (this.config.vectorConfig?.autoEmbedding) {
document.tags = await this.taggingSystem.autoTag(collection, document);
}
return await this.storage.insertOne(collection, document);
}
/**
* Insert multiple documents
*/
async insertMany(collection, documents) {
await this.ensureInitialized();
// Auto-tag documents if enabled
if (this.config.vectorConfig?.autoEmbedding) {
for (const document of documents) {
document.tags = await this.taggingSystem.autoTag(collection, document);
}
}
return await this.storage.insertMany(collection, documents);
}
/**
* Find documents by filter
*/
async find(collection, filter = {}, options = {}) {
await this.ensureInitialized();
// Track query pattern for auto-indexing
this.indexManager.trackQueryPattern(this.config.name, collection, filter, options);
return await this.storage.find(collection, filter, options);
}
/**
* Find a single document
*/
async findOne(collection, filter = {}, options = {}) {
await this.ensureInitialized();
return await this.storage.findOne(collection, filter, options);
}
/**
* Update a single document
*/
async updateOne(collection, filter, update, options = {}) {
await this.ensureInitialized();
if (this.config.enableRelationships) {
return await this.relationshipManager.updateWithRelationships(collection, filter, update);
}
else {
return await this.storage.updateOne(collection, filter, update, options);
}
}
/**
* Update multiple documents
*/
async updateMany(collection, filter, update, options = {}) {
await this.ensureInitialized();
// For bulk updates, use the bulk operations manager
const bulkOps = [{
updateMany: {
filter,
update: update,
upsert: options.upsert,
arrayFilters: options.arrayFilters
}
}];
const bulkResult = await this.bulkOperationsManager.bulkWrite(collection, bulkOps);
return {
acknowledged: bulkResult.acknowledged,
matchedCount: bulkResult.matchedCount,
modifiedCount: bulkResult.modifiedCount,
upsertedId: Object.values(bulkResult.upsertedIds)[0],
upsertedCount: bulkResult.upsertedCount
};
}
/**
* Replace a single document
*/
async replaceOne(collection, filter, replacement, options = {}) {
await this.ensureInitialized();
return await this.storage.updateOne(collection, filter, replacement, options);
}
/**
* Delete a single document
*/
async deleteOne(collection, filter) {
await this.ensureInitialized();
if (this.config.enableRelationships) {
await this.relationshipManager.deleteWithRelationships(collection, filter);
return { acknowledged: true, deletedCount: 1 };
}
else {
return await this.storage.deleteOne(collection, filter);
}
}
/**
* Delete multiple documents
*/
async deleteMany(collection, filter) {
await this.ensureInitialized();
return await this.storage.deleteMany(collection, filter);
}
/**
* Count documents matching filter
*/
async countDocuments(collection, filter = {}) {
await this.ensureInitialized();
return await this.storage.countDocuments(collection, filter);
}
// ===============================
// Advanced Query Operations
// ===============================
/**
* Execute aggregation pipeline
*/
async aggregate(collection, pipeline, options = {}) {
await this.ensureInitialized();
return await this.queryEngine.executeAggregation(this.config.name, collection, pipeline, options);
}
/**
* Explain query execution plan
*/
async explain(collection, filter, options = {}) {
await this.ensureInitialized();
return await this.queryEngine.explainQuery(this.config.name, collection, filter, options);
}
// ===============================
// Hybrid Search Operations
// ===============================
/**
* Hybrid search combining text, vector, and metadata
*/
async hybridSearch(collection, query) {
await this.ensureInitialized();
return await this.hybridSearchEngine.hybridSearch(this.config.name, collection, query);
}
/**
* Text search with optional vector boost
*/
async textSearch(collection, searchText, options = {}) {
await this.ensureInitialized();
return await this.hybridSearchEngine.textSearch(this.config.name, collection, searchText, options);
}
/**
* Vector similarity search
*/
async vectorSearch(collection, queryVector, options = {}) {
await this.ensureInitialized();
return await this.hybridSearchEngine.vectorSearch(this.config.name, collection, queryVector, options);
}
/**
* Semantic search using text embedding
*/
async semanticSearch(collection, searchText, options = {}) {
await this.ensureInitialized();
return await this.hybridSearchEngine.semanticSearch(this.config.name, collection, searchText, options);
}
/**
* Find similar documents
*/
async findSimilarDocuments(collection, documentId, options = {}) {
await this.ensureInitialized();
return await this.hybridSearchEngine.findSimilarDocuments(this.config.name, collection, documentId, options);
}
/**
* Get personalized recommendations
*/
async getRecommendations(collection, userHistory, options = {}) {
await this.ensureInitialized();
return await this.hybridSearchEngine.getRecommendations(this.config.name, collection, userHistory, options);
}
// ===============================
// Relationship Operations
// ===============================
/**
* Define a relationship between collections
*/
async defineRelationship(sourceCollection, targetCollection, relationship) {
await this.ensureInitialized();
return await this.relationshipManager.defineRelationship(sourceCollection, targetCollection, relationship);
}
/**
* Populate document with related data
*/
async populate(collection, document, populateOptions) {
await this.ensureInitialized();
return await this.relationshipManager.populate(collection, document, populateOptions);
}
/**
* Find documents with automatic population
*/
async findWithPopulate(collection, filter, populateOptions, findOptions = {}) {
await this.ensureInitialized();
return await this.relationshipManager.findWithPopulate(collection, filter, populateOptions, findOptions);
}
// ===============================
// Bulk Operations
// ===============================
/**
* Execute bulk write operations
*/
async bulkWrite(collection, operations, options = {}) {
await this.ensureInitialized();
return await this.bulkOperationsManager.bulkWrite(collection, operations, options);
}
/**
* Stream insert large datasets
*/
async streamInsert(collection, documentStream, options = {}) {
await this.ensureInitialized();
return await this.bulkOperationsManager.streamInsert(collection, documentStream, options);
}
/**
* Create a document stream for real-time processing
*/
createDocumentStream(collection, config) {
return this.bulkOperationsManager.createDocumentStream(collection, config);
}
// ===============================
// Index Management
// ===============================
/**
* Create an index
*/
async createIndex(collection, indexSpec) {
await this.ensureInitialized();
return await this.indexManager.createIndex(this.config.name, collection, indexSpec);
}
/**
* Drop an index
*/
async dropIndex(collection, indexName) {
await this.ensureInitialized();
return await this.indexManager.dropIndex(this.config.name, collection, indexName);
}
/**
* List all indexes for a collection
*/
async listIndexes(collection) {
await this.ensureInitialized();
return await this.indexManager.listIndexes(this.config.name, collection);
}
/**
* Get index recommendations
*/
async getIndexRecommendations(collection) {
await this.ensureInitialized();
return await this.indexManager.getIndexRecommendations(this.config.name, collection);
}
/**
* Auto-create indexes based on query patterns
*/
async autoCreateIndexes(collection) {
await this.ensureInitialized();
return await this.indexManager.autoCreateIndexes(this.config.name, collection);
}
// ===============================
// Tagging and Metadata
// ===============================
/**
* Auto-tag a document
*/
async autoTag(collection, document, config = {}) {
await this.ensureInitialized();
return await this.taggingSystem.autoTag(collection, document, config);
}
/**
* Tag a document
*/
async tagDocument(collection, documentId, tags, options = {}) {
await this.ensureInitialized();
return await this.taggingSystem.tagDocument(collection, documentId, tags, options);
}
/**
* Find documents by tags
*/
async findByTags(collection, tags, options = {}) {
await this.ensureInitialized();
return await this.taggingSystem.findByTags(collection, tags, options);
}
/**
* Get tag suggestions
*/
async getTagSuggestions(collection, document, options = {}) {
await this.ensureInitialized();
return await this.taggingSystem.getTagSuggestions(collection, document, options);
}
/**
* Get tag statistics
*/
async getTagStats(collection, options = {}) {
await this.ensureInitialized();
return await this.taggingSystem.getTagStats(collection, options);
}
// ===============================
// Database Management
// ===============================
/**
* Get database statistics
*/
async stats() {
await this.ensureInitialized();
try {
// This is a simplified implementation
// In a real scenario, you'd aggregate across all collections
const totalDocs = await this.storage.countDocuments('*', {});
return {
totalDocuments: totalDocs,
totalSize: 0, // Would calculate actual size
averageDocumentSize: 0,
indexCount: 0,
totalIndexSize: 0,
collections: 0,
vectorDocuments: 0,
lastOptimized: new Date()
};
}
catch (error) {
throw new DocumentError(`Failed to get database stats: ${error.message}`, 'STATS_ERROR');
}
}
/**
* Health check
*/
async ping() {
try {
return await this.storage.ping();
}
catch (error) {
return false;
}
}
/**
* Close database connections
*/
async close() {
try {
await this.bulkOperationsManager.stopAllStreams();
this.hybridSearchEngine.clearSearchCache();
this.relationshipManager.clearPopulateCache();
console.log(`EdgeDocumentDB closed: ${this.config.name}`);
}
catch (error) {
console.warn('Error during database close:', error.message);
}
}
// ===============================
// Static Factory Methods
// ===============================
/**
* Create a document database with simplified configuration
*/
static async create(config) {
const dbConfig = {
name: config.name,
d1Database: config.d1Database,
kvStore: config.kvStore,
r2Bucket: config.r2Bucket,
// Default configuration
maxDocumentSize: 16 * 1024 * 1024, // 16MB
queryTimeout: 30000,
batchSize: 100,
enableQueryCache: true,
queryCacheTTL: 300,
cacheSize: 100,
enableAutoIndexing: true,
autoIndexThreshold: 1000,
maxIndexedFields: 20,
vectorConfig: {
enabled: true,
defaultDimensions: 1536,
defaultModel: 'text-embedding-ada-002',
autoEmbedding: false,
embeddingFields: ['content', 'text', 'description']
},
enableValidation: true,
enableSchemaEvolution: true,
enableChangeStreams: true,
maxChangeStreamConnections: 1000,
enableQueryLogging: false,
enablePerformanceMetrics: true,
enableRelationships: true,
populateDepth: 3,
bulkWriteBatchSize: 1000,
bulkWriteParallelism: 4,
// Override with user options
...config.options
};
const db = new EdgeDocumentDB(dbConfig);
await db.initialize();
return db;
}
// ===============================
// Private Methods
// ===============================
async ensureInitialized() {
if (!this.initialized) {
await this.initialize();
}
}
}
//# sourceMappingURL=edge-document-db.js.map