react-native-sst-storage-db
Version:
A powerful file-based MongoDB-like database for React Native. Single JSON file storage with collections, advanced querying, indexing, and atomic operations. No AsyncStorage dependency.
188 lines (161 loc) • 5.51 kB
JavaScript
/**
* Collection Indexing Methods
* Provides indexing functionality for improved query performance
*/
class CollectionIndexing {
/**
* Update indexes when inserting a document
*/
static updateIndexesForInsert(collection, document) {
const indexes = collection._getCollectionIndexes();
for (const [field, index] of Object.entries(indexes)) {
const value = collection.queryEngine.getNestedValue(document, field);
if (value !== undefined) {
if (!index[value]) {
index[value] = [];
}
index[value].push(document._id);
}
}
}
/**
* Update indexes when updating a document
*/
static updateIndexesForUpdate(collection, oldDocument, newDocument) {
const indexes = collection._getCollectionIndexes();
for (const [field, index] of Object.entries(indexes)) {
const oldValue = collection.queryEngine.getNestedValue(oldDocument, field);
const newValue = collection.queryEngine.getNestedValue(newDocument, field);
// Remove old value from index
if (oldValue !== undefined && index[oldValue]) {
const idIndex = index[oldValue].indexOf(oldDocument._id);
if (idIndex !== -1) {
index[oldValue].splice(idIndex, 1);
if (index[oldValue].length === 0) {
delete index[oldValue];
}
}
}
// Add new value to index
if (newValue !== undefined) {
if (!index[newValue]) {
index[newValue] = [];
}
if (!index[newValue].includes(newDocument._id)) {
index[newValue].push(newDocument._id);
}
}
}
}
/**
* Update indexes when deleting a document
*/
static updateIndexesForDelete(collection, document) {
const indexes = collection._getCollectionIndexes();
for (const [field, index] of Object.entries(indexes)) {
const value = collection.queryEngine.getNestedValue(document, field);
if (value !== undefined && index[value]) {
const idIndex = index[value].indexOf(document._id);
if (idIndex !== -1) {
index[value].splice(idIndex, 1);
if (index[value].length === 0) {
delete index[value];
}
}
}
}
}
/**
* Create an index on a field
*/
static createIndex(collection, field) {
const indexes = collection._getCollectionIndexes();
if (indexes[field]) {
return; // Index already exists
}
// Create new index
indexes[field] = {};
const collectionData = collection._getCollectionData();
// Build index from existing documents
for (const document of collectionData) {
const value = collection.queryEngine.getNestedValue(document, field);
if (value !== undefined) {
if (!indexes[field][value]) {
indexes[field][value] = [];
}
indexes[field][value].push(document._id);
}
}
collection.storage.log(`✓ Index created on field: ${field}`);
}
/**
* Drop an index
*/
static dropIndex(collection, field) {
const indexes = collection._getCollectionIndexes();
if (indexes[field]) {
delete indexes[field];
collection.storage.log(`✓ Index dropped on field: ${field}`);
}
}
/**
* Get index statistics
*/
static getIndexStats(collection) {
const indexes = collection._getCollectionIndexes();
const stats = {};
for (const [field, index] of Object.entries(indexes)) {
stats[field] = {
keyCount: Object.keys(index).length,
totalDocuments: Object.values(index).reduce((sum, ids) => sum + ids.length, 0)
};
}
return stats;
}
/**
* Rebuild all indexes
*/
static rebuildIndexes(collection) {
const indexes = collection._getCollectionIndexes();
const fields = Object.keys(indexes);
// Clear existing indexes
for (const field of fields) {
indexes[field] = {};
}
// Rebuild from collection data
const collectionData = collection._getCollectionData();
for (const document of collectionData) {
for (const field of fields) {
const value = collection.queryEngine.getNestedValue(document, field);
if (value !== undefined) {
if (!indexes[field][value]) {
indexes[field][value] = [];
}
indexes[field][value].push(document._id);
}
}
}
collection.storage.log(`✓ Rebuilt ${fields.length} indexes`);
}
/**
* Use index to optimize queries (basic implementation)
*/
static optimizeQuery(collection, query) {
const indexes = collection._getCollectionIndexes();
const collectionData = collection._getCollectionData();
// Check if query can use an index
for (const [field, condition] of Object.entries(query)) {
if (indexes[field] && typeof condition !== 'object') {
// Simple equality query can use index
const ids = indexes[field][condition] || [];
const results = ids.map(id =>
collectionData.find(doc => doc._id === id)
).filter(doc => doc !== undefined);
return results;
}
}
// No index optimization possible
return null;
}
}
module.exports = CollectionIndexing;