diff --git a/package.json b/package.json index 2890ac2..2b22373 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "eslint": "8.47.0", "jsdoc-babel": "^0.5.0", "jsdoc-to-markdown": "^7.1.1", - "mongoose": "^7.4.0", + "mongoose": "^7.5.0", "nyc": "^15.1.0", "sinon": "15.2.0", "ts-mocha": "^10.0.0", @@ -94,7 +94,7 @@ "winston": "^3.7.2" }, "peerDependencies": { - "mongoose": "^7.4.0" + "mongoose": "^7.5.0" }, "engines": { "node": ">=14.0.0" diff --git a/src/collections/collection.ts b/src/collections/collection.ts index b215505..16d8ff7 100644 --- a/src/collections/collection.ts +++ b/src/collections/collection.ts @@ -107,25 +107,36 @@ export class Collection { async updateOne(filter: Record, update: Record, options?: UpdateOneOptions) { return executeOperation(async (): Promise => { - const command = { - updateOne: { - filter, - update, - options - } - }; - setDefaultIdForUpsert(command.updateOne); - const updateOneResp = await this.httpClient.executeCommand(command, updateOneInternalOptionsKeys); - const resp = { - modifiedCount: updateOneResp.status.modifiedCount, - matchedCount: updateOneResp.status.matchedCount, - acknowledged: true - } as JSONAPIUpdateResult; - if (updateOneResp.status.upsertedId) { - resp.upsertedId = updateOneResp.status.upsertedId; - resp.upsertedCount = 1; - } - return resp; + type UpdateOneCommand = { + updateOne: { + filter?: Record, + sort?: SortOption, + update?: Record, + options?: UpdateOneOptions + } + } + const command: UpdateOneCommand = { + updateOne: { + filter, + update, + options + } + }; + if (options?.sort != null) { + command.updateOne.sort = options?.sort; + } + setDefaultIdForUpsert(command.updateOne); + const updateOneResp = await this.httpClient.executeCommand(command, updateOneInternalOptionsKeys); + const resp = { + modifiedCount: updateOneResp.status.modifiedCount, + matchedCount: updateOneResp.status.matchedCount, + acknowledged: true + } as JSONAPIUpdateResult; + if (updateOneResp.status.upsertedId) { + resp.upsertedId = updateOneResp.status.upsertedId; + resp.upsertedCount = 1; + } + return resp; }); } diff --git a/tests/driver/api.test.ts b/tests/driver/api.test.ts index f1bcc15..8630f30 100644 --- a/tests/driver/api.test.ts +++ b/tests/driver/api.test.ts @@ -777,16 +777,7 @@ describe(`Mongoose Model API level tests`, async () => { ); let Vector: Model; - beforeEach(async () => { - mongooseInstance = await getInstance(); - const options = { - username: process.env.STARGATE_USERNAME, - password: process.env.STARGATE_PASSWORD, - authUrl: process.env.STARGATE_AUTH_URL, - logSkippedOptions: true - }; - await mongooseInstance.connect(dbUri, options); - + this.beforeEach(async function() { await mongooseInstance.connection.dropCollection('vector'); Vector = mongooseInstance.model( 'Vector', @@ -807,6 +798,15 @@ describe(`Mongoose Model API level tests`, async () => { ]); }); + it('supports updating $vector with save()', async function() { + const vector = await Vector.findOne({ name: 'Test vector 1' }).orFail(); + vector.$vector = [1, 101]; + await vector.save(); + + const { $vector } = await Vector.findOne({ name: 'Test vector 1' }).orFail(); + assert.deepStrictEqual($vector, [1, 101]); + }); + it('supports sort() with $meta with find()', async function() { let res = await Vector. find({}). @@ -815,8 +815,10 @@ describe(`Mongoose Model API level tests`, async () => { res = await Vector. find({}). + select({ $vector: 0 }). sort({ $vector: { $meta: [99, 1] } }); assert.deepStrictEqual(res.map(doc => doc.name), ['Test vector 2', 'Test vector 1']); + assert.deepStrictEqual(res.map(doc => doc.$vector), [undefined, undefined]); res = await Vector. find({}). @@ -824,47 +826,98 @@ describe(`Mongoose Model API level tests`, async () => { sort({ $vector: { $meta: [99, 1] } }); assert.deepStrictEqual(res.map(doc => doc.name), ['Test vector 2', 'Test vector 1']); + res = await Vector. + findOne({}). + sort({ $vector: { $meta: [99, 1] } }); + assert.deepStrictEqual(res.name, 'Test vector 2'); + await assert.rejects( Vector.find().limit(1001).sort({ $vector: { $meta: [99, 1] } }), /limit options should not be greater than 1000 for vector search/ ); }); - it('supports sort() with $meta with findOne()', async function() { - let res = await Vector. - findOne({}). - sort({ $vector: { $meta: [1, 99] } }); - assert.deepStrictEqual(res.name, 'Test vector 1'); - - res = await Vector. - findOne({}). + it('supports sort() with $meta with updateOne()', async function() { + await Vector. + updateOne( + {}, + { name: 'found vector', $vector: [990, 1] } + ). sort({ $vector: { $meta: [99, 1] } }); - assert.deepStrictEqual(res.name, 'Test vector 2'); + const vectors = await Vector.find().limit(20).sort({ name: 1 }); + assert.deepStrictEqual(vectors.map(v => v.name), ['Test vector 1', 'found vector']); + assert.deepStrictEqual(vectors.map(v => v.$vector), [[1, 100], [990, 1]]); }); it('supports sort() with $meta with findOneAndUpdate()', async function() { const res = await Vector. - findOneAndUpdate({}, { name: 'found vector' }, { returnDocument: 'after' }). + findOneAndUpdate( + {}, + { name: 'found vector', $vector: [990, 1] }, + { returnDocument: 'before' } + ). sort({ $vector: { $meta: [99, 1] } }); assert.deepStrictEqual(res.$vector, [100, 1]); - assert.strictEqual(res.name, 'found vector'); + assert.strictEqual(res.name, 'Test vector 2'); + + const doc = await Vector.findById(res._id); + assert.strictEqual(doc.name, 'found vector'); + assert.deepStrictEqual(doc.$vector, [990, 1]); + }); + + it('supports $setOnInsert of $vector with findOneAndUpdate()', async function() { + let res = await Vector. + findOneAndUpdate( + { name: 'Test vector 2' }, + { $setOnInsert: { $vector: [990, 1] } }, + { returnDocument: 'after', upsert: true } + ); + assert.deepStrictEqual(res.$vector, [100, 1]); + assert.strictEqual(res.name, 'Test vector 2'); + + res = await Vector. + findOneAndUpdate( + { name: 'Test vector 3' }, + { $setOnInsert: { $vector: [990, 1] } }, + { returnDocument: 'after', upsert: true } + ); + assert.deepStrictEqual(res.$vector, [990, 1]); + assert.strictEqual(res.name, 'Test vector 3'); + }); + + it('supports $unset of $vector with findOneAndUpdate()', async function() { + const res = await Vector. + findOneAndUpdate( + { name: 'Test vector 2' }, + { $unset: { $vector: 1 } }, + { returnDocument: 'after' } + ); + assert.deepStrictEqual(res.$vector, undefined); + assert.strictEqual(res.name, 'Test vector 2'); }); it('supports sort() with $meta with findOneAndReplace()', async function() { const res = await Vector. findOneAndReplace( {}, - { name: 'found vector' }, + { name: 'found vector', $vector: [990, 1] }, { returnDocument: 'before' } ). sort({ $vector: { $meta: [99, 1] } }); assert.deepStrictEqual(res.$vector, [100, 1]); assert.strictEqual(res.name, 'Test vector 2'); + + const doc = await Vector.findById(res._id); + assert.strictEqual(doc.name, 'found vector'); + assert.deepStrictEqual(doc.$vector, [990, 1]); }); it('supports sort() with $meta with findOneAndDelete()', async function() { const res = await Vector. - findOneAndDelete({}, { name: 'found vector' }, { returnDocument: 'before' }). + findOneAndDelete( + {}, + { returnDocument: 'before' } + ). sort({ $vector: { $meta: [1, 99] } }); assert.deepStrictEqual(res.$vector, [1, 100]); assert.strictEqual(res.name, 'Test vector 1');