Я бы порекомендовал иерархическую структуру, примерно такую:
const db = new Dexie('filesystem');
db.version(1).stores({
files: `
[parentDir+name],
parentDir`
});
Используя составной индекс [parentDir + name], БД гарантирует, что никакие два элемента не будут иметь одинаковый путь.
Индексируя parentDir, вы можете перечислять как прямых, так и рекурсивных детей только с помощью индекса.
Некоторые примеры:
function createDir(parentDir, name) {
// The following transaction will fail if
// the combination parentDir+name already exists or
// represents a file.
return db.files.add({parentDir, name, type: "dir"});
}
function createFile(parentDir, filename, blob) {
return db.transaction('rw', db.files, async ()=>{
// Verify parentDir exists and is a directory:
const dir = await db.files.get({
parentDir: parentDir
});
if (!dir) throw new Error("Parent dir not found");
if (dir.type !== 'dir') throw new Error("Parent is not a dir");
await db.files.add({
type: 'file',
name: filename,
parentDir,
blob
});
});
}
/** List all files and folders within given diretory */
function listDirectory(dirPath) {
return db.files
.where({parentDir: dirPath})
.toArray();
}
/** List all files and folders recursively within given diretory */
function listDirectoryRecursively(dirPath) {
return db.files
.where('parentDir')
.startsWith(dirPath)
.toArray();
}
Перемещение файла или каталога будет быстрым, поскольку вы можете получить доступ ко всему поддереву за один запрос.
function moveDirectory (oldParentDir, name, newParentDir) {
return db.transaction('rw', db.files, async ()=>{
// Move the directory itself:
await db.files
.where({parentDir: oldParentDir, name: name})
.modify(item => item.parentDir = newDir);
// Move all descendants:
await db.files
.where('parentDir')
.startsWith(oldParentDir + "/" + name)
.modify(item =>
item.parentDir = newParentDir +
item.parentDir.substr(oldParentDir.length) + // strip start
"/" + item.name);
});
}