Skip to content

Commit

Permalink
Merge pull request #372 from sekko27/main
Browse files Browse the repository at this point in the history
IndexOptionsConflict for chunk collection - pr

Signed-off-by: lucsoft <[email protected]>
  • Loading branch information
lucsoft authored Aug 10, 2022
2 parents ed42dc1 + ddb9811 commit d45dd12
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 88 deletions.
133 changes: 45 additions & 88 deletions src/gridfs/indexes.ts
Original file line number Diff line number Diff line change
@@ -1,103 +1,60 @@
import { Document } from "../../deps.ts";
import { Collection } from "../collection/collection.ts";
import { Chunk, File } from "../types/gridfs.ts";
import { IndexOptions } from "../types.ts";

async function ensureIndex<T>(
index: IndexOptions,
collection: Collection<T>,
): Promise<ReturnType<Collection<T>["createIndexes"]>> {
// We need to check collection emptiness (ns not found error for listIndexes on empty collection)
const doc = await collection.findOne({}, { projection: { _id: 1 } });
if (doc === undefined) {
return collection.createIndexes({ indexes: [index] });
}
const keys = Object.keys(index.key);
const indexes = await collection.listIndexes().toArray();
const existing = indexes.find(({ key }) => {
const currentKeys = Object.keys(key);
return currentKeys.length === keys.length &&
currentKeys.every((k) => keys.includes(k));
});
if (existing === undefined) {
return collection.createIndexes({ indexes: [index] });
} else {
return {
ok: 1,
createdCollectionAutomatically: false,
numIndexesBefore: indexes.length,
numIndexesAfter: indexes.length,
};
}
}

const fileIndexSpec = {
name: "gridFSFiles",
key: { filename: 1, uploadDate: 1 },
background: false,
};
export function createFileIndex(collection: Collection<File>) {
const index = { filename: 1, uploadDate: 1 };

return collection.createIndexes({
indexes: [
{
name: "gridFSFiles",
key: index,
background: false,
},
],
});
return ensureIndex<File>(fileIndexSpec, collection);
}
export function createChunksIndex(collection: Collection<Chunk>) {
// deno-lint-ignore camelcase
const index = { files_id: 1, n: 1 };

return collection.createIndexes({
indexes: [
{
name: "gridFSFiles",
key: index,
unique: true,
background: false,
},
],
});
const chunkIndexSpec = {
name: "gridFSFiles",
key: { files_id: 1, n: 1 },
unique: true,
background: false,
};
export function createChunksIndex(collection: Collection<Chunk>) {
return ensureIndex<Chunk>(chunkIndexSpec, collection);
}

export async function checkIndexes(
filesCollection: Collection<File>,
chunksCollection: Collection<Chunk>,
hasCheckedIndexes: (value: boolean) => void,
) {
const filesCollectionIsEmpty = !(await filesCollection.findOne(
{},
{
projection: { _id: 1 },
},
));

const chunksCollectionIsEmpty = !(await chunksCollection.findOne(
{},
{
projection: { _id: 1 },
},
));

if (filesCollectionIsEmpty || chunksCollectionIsEmpty) {
// At least one collection is empty so we create indexes
await createFileIndex(filesCollection);
await createChunksIndex(chunksCollection);
hasCheckedIndexes(true);
return;
}

// Now check that the right indexes are there
const fileIndexes = await filesCollection.listIndexes().toArray();
let hasFileIndex = false;

if (fileIndexes) {
fileIndexes.forEach((index) => {
const keys = Object.keys(index.key);
if (
keys.length === 2 &&
index.key.filename === 1 &&
index.key.uploadDate === 1
) {
hasFileIndex = true;
}
});
}

if (!hasFileIndex) {
await createFileIndex(filesCollection);
}

const chunkIndexes = await chunksCollection.listIndexes().toArray();
let hasChunksIndex = false;

if (chunkIndexes) {
chunkIndexes.forEach((index: Document) => {
const keys = Object.keys(index.key);
if (
keys.length === 2 &&
index.key.filename === 1 &&
index.key.uploadDate === 1 &&
index.options.unique
) {
hasChunksIndex = true;
}
});
}

if (!hasChunksIndex) {
await createChunksIndex(chunksCollection);
}
await createFileIndex(filesCollection);
await createChunksIndex(chunksCollection);
hasCheckedIndexes(true);
}
22 changes: 22 additions & 0 deletions tests/cases/06_gridfs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,25 @@ testWithClient(
assert(!file[0]);
},
);

// https://www.mongodb.com/docs/manual/reference/command/createIndexes/#considerations
testWithClient(
"GridFS: Creating indexes - skip index creation on same index keys",
async (client) => {
const addAsset = async (index: number) => {
const db = client.database("test");
const bucket = new GridFSBucket(db, {
bucketName: "sameKeys",
});
const upstream = await bucket.openUploadStream(`test-asset-${index}`);
const writer = upstream.getWriter();
await writer.write(new TextEncoder().encode(`[asset${index}]`));
await writer.close();
return {
files: await db.collection("sameKeys.files").listIndexes().toArray(),
chunks: await db.collection("sameKeys.chunks").listIndexes().toArray(),
};
};
assertEquals(await addAsset(0), await addAsset(1));
},
);

0 comments on commit d45dd12

Please sign in to comment.