Skip to content

Commit

Permalink
fix(mongo): don't rename id to _id for embeddables and entities w…
Browse files Browse the repository at this point in the history
…ithout serialized PK

Closes #4960
  • Loading branch information
B4nan committed Nov 25, 2023
1 parent 5820d66 commit 0cee82d
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 1 deletion.
5 changes: 4 additions & 1 deletion packages/mongodb/src/MongoDriver.ts
Expand Up @@ -226,9 +226,12 @@ export class MongoDriver extends DatabaseDriver<MongoConnection> {
private renameFields<T extends object>(entityName: string, data: T, where = false, object?: boolean): T {
// copy to new variable to prevent changing the T type or doing as unknown casts
const copiedData: Dictionary = Object.assign({}, data); // copy first
Utils.renameKey(copiedData, 'id', '_id');
const meta = this.metadata.find(entityName);

if (meta?.serializedPrimaryKey && !meta.embeddable && meta.serializedPrimaryKey !== meta.primaryKeys[0]) {
Utils.renameKey(copiedData, meta.serializedPrimaryKey, meta.primaryKeys[0]);
}

if (meta && !meta.embeddable) {
this.inlineEmbeddables(meta, copiedData, where);
}
Expand Down
114 changes: 114 additions & 0 deletions tests/issues/GH4960.test.ts
@@ -0,0 +1,114 @@
import { Entity, PrimaryKey, Property, Embedded, Opt, SerializedPrimaryKey, Embeddable } from '@mikro-orm/core';
import { ObjectId, MikroORM, wrap } from '@mikro-orm/mongodb';

@Embeddable()
class StripeSubscription {

@Property()
id!: string;

@Property()
start!: Date;

@Property()
end!: Date;

@Property({ type: 'string' })
status!: string;

}

@Embeddable()
class StripeSubscription2 {

@Property()
stripeId!: string;

@Property()
start!: Date;

@Property()
end!: Date;

@Property({ type: 'string' })
status!: string;

}

@Entity()
class User {

@PrimaryKey()
_id!: ObjectId;

@SerializedPrimaryKey()
id!: string;

@Property()
name: string;

@Property({ unique: true })
email: string;

@Embedded(() => StripeSubscription, { array: true })
stripeSubscriptions: StripeSubscription[] & Opt = [];

@Embedded(() => StripeSubscription2, { array: true })
stripeSubscriptions2: StripeSubscription2[] & Opt = [];

constructor(name: string, email: string) {
this.name = name;
this.email = email;
}

}
let orm: MikroORM;

beforeAll(async () => {
orm = await MikroORM.init({
clientUrl: 'mongodb://localhost:27017/mikro_orm_4960',
entities: [User, StripeSubscription, StripeSubscription2],
});
await orm.schema.refreshDatabase();
});

afterAll(async () => {
await orm.close(true);
});

test('basic CRUD example', async () => {
orm.em.create(User, { name: 'Foo', email: 'foo' });
await orm.em.flush();
orm.em.clear();

const user = await orm.em.findOneOrFail(User, { email: 'foo' });
expect(user.name).toBe('Foo');
user.name = 'Bar';
orm.em.remove(user);
await orm.em.flush();

const count = await orm.em.count(User, { email: 'foo' });
expect(count).toBe(0);
});

test('Test Embeddabled', async () => {
const user = orm.em.create(User, { name: 'Foo', email: 'foo' });
await orm.em.flush();

const sub1 = new StripeSubscription();
wrap(sub1).assign({ id: 'aaa', start: new Date(), end: new Date(), status: 'ok' });
user.stripeSubscriptions = [...user.stripeSubscriptions, sub1];

const sub2 = new StripeSubscription2();
wrap(sub2).assign({ stripeId: 'aaa', start: new Date(), end: new Date(), status: 'ok' });
user.stripeSubscriptions2 = [...user.stripeSubscriptions2, sub2];

await orm.em.flush();

expect(user.stripeSubscriptions[0].id).toBe('aaa');
expect(user.stripeSubscriptions2[0].stripeId).toBe('aaa');

const user2 = await orm.em.findOneOrFail(User, { email: 'foo' });
expect(user2.stripeSubscriptions[0].id).toBe('aaa');
expect(user2.stripeSubscriptions2[0].stripeId).toBe('aaa');
});

0 comments on commit 0cee82d

Please sign in to comment.