Skip to content

Commit

Permalink
fix(NODE-5791): type error with $addToSet in bulkWrite (#3953)
Browse files Browse the repository at this point in the history
Co-authored-by: Neal Beeken <neal.beeken@mongodb.com>
  • Loading branch information
alenakhineika and nbbeeken committed Jan 3, 2024
1 parent efece79 commit b93d405
Show file tree
Hide file tree
Showing 5 changed files with 288 additions and 11 deletions.
16 changes: 12 additions & 4 deletions src/bulk/common.ts
Expand Up @@ -87,8 +87,12 @@ export interface ReplaceOneModel<TSchema extends Document = Document> {
export interface UpdateOneModel<TSchema extends Document = Document> {
/** The filter to limit the updated documents. */
filter: Filter<TSchema>;
/** A document or pipeline containing update operators. */
update: UpdateFilter<TSchema> | UpdateFilter<TSchema>[];
/**
* The modifications to apply. The value can be either:
* UpdateFilter<TSchema> - A document that contains update operator expressions,
* Document[] - an aggregation pipeline.
*/
update: UpdateFilter<TSchema> | Document[];
/** A set of filters specifying to which array elements an update should apply. */
arrayFilters?: Document[];
/** Specifies a collation. */
Expand All @@ -103,8 +107,12 @@ export interface UpdateOneModel<TSchema extends Document = Document> {
export interface UpdateManyModel<TSchema extends Document = Document> {
/** The filter to limit the updated documents. */
filter: Filter<TSchema>;
/** A document or pipeline containing update operators. */
update: UpdateFilter<TSchema> | UpdateFilter<TSchema>[];
/**
* The modifications to apply. The value can be either:
* UpdateFilter<TSchema> - A document that contains update operator expressions,
* Document[] - an aggregation pipeline.
*/
update: UpdateFilter<TSchema> | Document[];
/** A set of filters specifying to which array elements an update should apply. */
arrayFilters?: Document[];
/** Specifies a collation. */
Expand Down
18 changes: 13 additions & 5 deletions src/collection.ts
Expand Up @@ -339,13 +339,17 @@ export class Collection<TSchema extends Document = Document> {
/**
* Update a single document in a collection
*
* The value of `update` can be either:
* - UpdateFilter<TSchema> - A document that contains update operator expressions,
* - Document[] - an aggregation pipeline.
*
* @param filter - The filter used to select the document to update
* @param update - The update operations to be applied to the document
* @param update - The modifications to apply
* @param options - Optional settings for the command
*/
async updateOne(
filter: Filter<TSchema>,
update: UpdateFilter<TSchema> | Partial<TSchema>,
update: UpdateFilter<TSchema> | Document[],
options?: UpdateOptions
): Promise<UpdateResult<TSchema>> {
return executeOperation(
Expand Down Expand Up @@ -385,13 +389,17 @@ export class Collection<TSchema extends Document = Document> {
/**
* Update multiple documents in a collection
*
* @param filter - The filter used to select the documents to update
* @param update - The update operations to be applied to the documents
* The value of `update` can be either:
* - UpdateFilter<TSchema> - A document that contains update operator expressions,
* - Document[] - an aggregation pipeline.
*
* @param filter - The filter used to select the document to update
* @param update - The modifications to apply
* @param options - Optional settings for the command
*/
async updateMany(
filter: Filter<TSchema>,
update: UpdateFilter<TSchema>,
update: UpdateFilter<TSchema> | Document[],
options?: UpdateOptions
): Promise<UpdateResult<TSchema>> {
return executeOperation(
Expand Down
6 changes: 5 additions & 1 deletion src/mongo_types.ts
Expand Up @@ -243,7 +243,11 @@ export type SetFields<TSchema> = ({
readonly [key in KeysOfAType<TSchema, ReadonlyArray<any> | undefined>]?:
| OptionalId<Flatten<TSchema[key]>>
| AddToSetOperators<Array<OptionalId<Flatten<TSchema[key]>>>>;
} & NotAcceptedFields<TSchema, ReadonlyArray<any> | undefined>) & {
} & IsAny<
TSchema[keyof TSchema],
object,
NotAcceptedFields<TSchema, ReadonlyArray<any> | undefined>
>) & {
readonly [key: string]: AddToSetOperators<any> | any;
};

Expand Down
196 changes: 195 additions & 1 deletion test/types/community/collection/bulkWrite.test-d.ts
@@ -1,6 +1,6 @@
import { expectError } from 'tsd';

import { MongoClient, ObjectId } from '../../../mongodb';
import { type Collection, type Document, MongoClient, ObjectId } from '../../../mongodb';

// TODO(NODE-3347): Improve these tests to use more expect assertions

Expand Down Expand Up @@ -297,3 +297,197 @@ collectionType.bulkWrite([
}
}
]);

{
// NODE-5647 - Type error with $addToSet in bulkWrite
interface TestDocument {
readonly myId: number;
readonly mySet: number[];
readonly myAny: any;
}
const collection = undefined as unknown as Collection<TestDocument>;
expectError(
collection.bulkWrite([
{
updateOne: {
filter: { myId: 0 },
update: {
$addToSet: { mySet: 'value of other type' }
}
}
}
])
);
collection.bulkWrite([
{
updateOne: {
filter: { myId: 0 },
update: {
$addToSet: { mySet: 0 }
}
}
}
]);
collection.bulkWrite([
{
updateOne: {
filter: { myId: 0 },
update: {
$addToSet: { myAny: 1 }
}
}
}
]);
collection.bulkWrite([
{
updateOne: {
filter: { myId: 0 },
update: [
{
$addToSet: { myAny: 0 }
}
]
}
}
]);
expectError(
collection.bulkWrite([
{
updateMany: {
filter: { myId: 0 },
update: {
$addToSet: { mySet: 'value of other type' }
}
}
}
])
);
collection.bulkWrite([
{
updateMany: {
filter: { myId: 0 },
update: {
$addToSet: { mySet: 0 }
}
}
}
]);
collection.bulkWrite([
{
updateMany: {
filter: { myId: 0 },
update: {
$addToSet: { myAny: 1 }
}
}
}
]);
collection.bulkWrite([
{
updateMany: {
filter: { myId: 0 },
update: [
{
$addToSet: { mySet: 0 }
}
]
}
}
]);

interface IndexSingatureTestDocument extends Document {
readonly myId: number;
readonly mySet: number[];
}
const indexSingatureCollection = undefined as unknown as Collection<IndexSingatureTestDocument>;
indexSingatureCollection.bulkWrite([
{
updateOne: {
filter: { myId: 0 },
update: {
$addToSet: { mySet: 0 }
}
}
}
]);
indexSingatureCollection.bulkWrite([
{
updateOne: {
filter: { myId: 0 },
update: [
{
$addToSet: { mySet: 0 }
}
]
}
}
]);
indexSingatureCollection.bulkWrite([
{
updateMany: {
filter: { myId: 0 },
update: {
$addToSet: { mySet: 0 }
}
}
}
]);
indexSingatureCollection.bulkWrite([
{
updateMany: {
filter: { myId: 0 },
update: [
{
$addToSet: { mySet: 0 }
}
]
}
}
]);

const collectionOfAnyType = undefined as unknown as Collection<any>;
collectionOfAnyType.bulkWrite([
{
updateOne: {
filter: { myId: 0 },
update: {
$addToSet: { mySet: 0 }
}
}
}
]);
collectionOfAnyType.bulkWrite([
{
updateOne: {
filter: { myId: 0 },
update: [
{
$addToSet: { mySet: 0 }
}
]
}
}
]);
collectionOfAnyType.bulkWrite([
{
updateMany: {
filter: { myId: 0 },
update: {
$addToSet: { mySet: 0 }
}
}
}
]);
collectionOfAnyType.bulkWrite([
{
updateMany: {
filter: { myId: 0 },
update: [
{
$addToSet: { mySet: 0 }
}
]
}
}
]);
}
63 changes: 63 additions & 0 deletions test/types/community/collection/updateX.test-d.ts
Expand Up @@ -439,3 +439,66 @@ export async function testPushWithId(): Promise<void> {
collectionWithSchema.updateMany({}, {})
);
}

{
// NODE-5647 - Type error with $addToSet in bulkWrite
interface TestDocument {
readonly myId: number;
readonly mySet: number[];
readonly myAny: any;
}
const collection = undefined as unknown as Collection<TestDocument>;
expectError(collection.updateOne({ myId: 0 }, { $addToSet: { mySet: 'value of other type' } }));
collection.updateOne({ myId: 0 }, { $addToSet: { mySet: 0 } });
collection.updateOne({ myId: 0 }, { $addToSet: { myAny: 1 } });
collection.updateOne({ myId: 0 }, [
{
$addToSet: { mySet: 0 }
}
]);
expectError(collection.updateMany({ myId: 0 }, { $addToSet: { mySet: 'value of other type' } }));
collection.updateMany({ myId: 0 }, { $addToSet: { mySet: 0 } });
collection.updateMany({ myId: 0 }, { $addToSet: { myAny: 1 } });
collection.updateMany({ myId: 0 }, [
{
$addToSet: { mySet: 0 }
}
]);

interface IndexSingatureTestDocument extends Document {
readonly myId: number;
readonly mySet: number[];
readonly myAny: any;
}
const indexSingatureCollection = undefined as unknown as Collection<IndexSingatureTestDocument>;
indexSingatureCollection.updateOne({ myId: 0 }, { $addToSet: { mySet: 0 } });
indexSingatureCollection.updateOne({ myId: 0 }, { $addToSet: { myAny: 1 } });
indexSingatureCollection.updateOne({ myId: 0 }, [
{
$addToSet: { mySet: 0 }
}
]);
indexSingatureCollection.updateMany({ myId: 0 }, { $addToSet: { mySet: 0 } });
indexSingatureCollection.updateMany({ myId: 0 }, { $addToSet: { myAny: 1 } });
indexSingatureCollection.updateMany({ myId: 0 }, [
{
$addToSet: { mySet: 0 }
}
]);

const collectionOfAnyType = undefined as unknown as Collection<any>;
collectionOfAnyType.updateOne({ myId: 0 }, { $addToSet: { mySet: 0 } });
collectionOfAnyType.updateOne({ myId: 0 }, { $addToSet: { myAny: 1 } });
collectionOfAnyType.updateOne({ myId: 0 }, [
{
$addToSet: { mySet: 0 }
}
]);
collectionOfAnyType.updateMany({ myId: 0 }, { $addToSet: { mySet: 0 } });
collectionOfAnyType.updateMany({ myId: 0 }, { $addToSet: { myAny: 1 } });
collectionOfAnyType.updateMany({ myId: 0 }, [
{
$addToSet: { mySet: 0 }
}
]);
}

0 comments on commit b93d405

Please sign in to comment.