Skip to content

Commit

Permalink
make listIndexes() return index definition
Browse files Browse the repository at this point in the history
  • Loading branch information
vkarpov15 committed Jan 3, 2025
1 parent 8f1811f commit 62d5b72
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 10 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
"eslint": "~9.13",
"jsdoc-babel": "^0.5.0",
"jsdoc-to-markdown": "^7.1.1",
"mongoose": "^8.9.0",
"mongoose": "^8.9.3",
"nyc": "^17.1.0",
"sinon": "15.2.0",
"ts-mocha": "^10.0.0",
Expand Down
15 changes: 12 additions & 3 deletions src/driver/collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ import {
Sort as SortOptionInternal,
Table as AstraTable,
TableFilter,
CreateTableIndexOptions
CreateTableIndexOptions,
TableIndexOptions,
TableVectorIndexOptions
} from '@datastax/astra-db-ts';
import { serialize } from '../serialize';
import deserializeDoc from '../deserializeDoc';
Expand All @@ -47,6 +49,12 @@ type DeleteOneOptions = Omit<DeleteOneOptionsInternal, 'sort'> & { sort?: Mongoo
type ReplaceOneOptions = Omit<CollectionReplaceOneOptions, 'sort'> & { sort?: MongooseSortOption };
type UpdateOneOptions = Omit<UpdateOneOptionsInternal, 'sort'> & { sort?: MongooseSortOption };

interface StargateMongooseIndexDescription {
name: string,
definition: { column: string, options?: TableIndexOptions | TableVectorIndexOptions },
key: Record<string, 1>
}

/**
* Collection operations supported by the driver. This class is called "Collection" for consistency with Mongoose, because
* in Mongoose a Collection is the interface that Models and Queries use to communicate with the database. However, from
Expand Down Expand Up @@ -372,8 +380,9 @@ export class Collection<DocType extends Record<string, unknown> = Record<string,
if (this.collection instanceof AstraCollection) {
throw new OperationNotSupportedError('Cannot use listIndexes() with collections');
}
return new AsyncCursorPlaceholder<{ name: string, key: Record<string, 1> }>(
this.collection.listIndexes({ nameOnly: true }).then(indexes => indexes.map(name => ({ name, key: { [name]: 1 } })))
// Mongoose uses the `key` property of an index for index diffing in `cleanIndexes()` and `syncIndexes()`.
return new AsyncCursorPlaceholder<StargateMongooseIndexDescription>(
this.collection.listIndexes().then(indexes => indexes.map(index => ({ ...index, key: { [index.definition.column]: 1 } })))
);
}

Expand Down
58 changes: 52 additions & 6 deletions tests/driver/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,18 +260,46 @@ describe('Mongoose Model API level tests', async () => {
Product.schema.index({name: 1});
await collection.createIndex({ name: true });
await collection.createIndex({ price: true }, { name: 'will_drop_index' });
// @ts-expect-error
const droppedIndexes: string[] = await Product.cleanIndexes();

let indexes = await Product.listIndexes();
assert.deepStrictEqual(indexes, [
{
name: 'name',
definition: {
column: 'name',
options: { ascii: false, caseSensitive: true, normalize: false }
},
key: { name: 1 }
},
{
name: 'will_drop_index',
definition: { column: 'price', options: {} },
key: { price: 1 }
}
]);

const droppedIndexes = await Product.cleanIndexes();

// Drop "will_drop_index" because not in schema, but keep index on `name`
assert.deepStrictEqual(droppedIndexes, ['will_drop_index']);

indexes = await Product.listIndexes();
assert.deepStrictEqual(indexes, [
{
name: 'name',
definition: {
column: 'name',
options: { ascii: false, caseSensitive: true, normalize: false }
},
key: { name: 1 }
}
]);

await collection.dropIndex('name');

// @ts-expect-error
Product.schema._indexes = [];
} else {
// @ts-expect-error
const promise = Product.cleanIndexes();
const error: Error | null = await promise.then(() => null, (error: Error) => error);
assert.ok(error instanceof OperationNotSupportedError);
Expand Down Expand Up @@ -628,7 +656,16 @@ describe('Mongoose Model API level tests', async () => {
const collection = mongooseInstance.connection.collection(Product.collection.collectionName);
await collection.createIndex({ name: true }, { name: 'test_index' });
const indexes = await Product.listIndexes();
assert.ok(indexes.map(index => index.name).includes('test_index'));
assert.deepStrictEqual(indexes, [
{
name: 'test_index',
definition: {
column: 'name',
options: { ascii: false, caseSensitive: true, normalize: false }
},
key: { name: 1 }
}
]);
await collection.dropIndex('test_index');
} else {
const error: Error | null = await Product.listIndexes().then(() => null, error => error);
Expand Down Expand Up @@ -1003,11 +1040,20 @@ describe('Mongoose Model API level tests', async () => {
const collection = mongooseInstance.connection.collection(Product.collection.collectionName);
await collection.createIndex({ name: true }, { name: 'test_index' });
let indexes = await Product.listIndexes();
assert.ok(indexes.map(index => index.name).includes('test_index'));
assert.deepStrictEqual(indexes, [
{
name: 'test_index',
definition: {
column: 'name',
options: { ascii: false, caseSensitive: true, normalize: false }
},
key: { name: 1 }
}
]);

await collection.dropIndex('test_index');
indexes = await Product.listIndexes();
assert.ok(!indexes.map(index => index.name).includes('test_index'));
assert.deepStrictEqual(indexes, []);
} else {
await assert.rejects(
mongooseInstance.connection.collection(Product.collection.collectionName).dropIndex('sample index name'),
Expand Down

0 comments on commit 62d5b72

Please sign in to comment.