diff --git a/package.json b/package.json index 188dfa5..ea81df5 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/driver/collection.ts b/src/driver/collection.ts index b8b0ee6..52ef72d 100644 --- a/src/driver/collection.ts +++ b/src/driver/collection.ts @@ -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'; @@ -47,6 +49,12 @@ type DeleteOneOptions = Omit & { sort?: Mongoo type ReplaceOneOptions = Omit & { sort?: MongooseSortOption }; type UpdateOneOptions = Omit & { sort?: MongooseSortOption }; +interface StargateMongooseIndexDescription { + name: string, + definition: { column: string, options?: TableIndexOptions | TableVectorIndexOptions }, + key: Record +} + /** * 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 @@ -372,8 +380,9 @@ export class Collection = Record }>( - 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( + this.collection.listIndexes().then(indexes => indexes.map(index => ({ ...index, key: { [index.definition.column]: 1 } }))) ); } diff --git a/tests/driver/api.test.ts b/tests/driver/api.test.ts index 49b1e31..4eb729b 100644 --- a/tests/driver/api.test.ts +++ b/tests/driver/api.test.ts @@ -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); @@ -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); @@ -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'),