Skip to content

Commit

Permalink
fix(mongo): fix querying object embedded JSON properties
Browse files Browse the repository at this point in the history
Closes #4755
  • Loading branch information
B4nan committed Sep 30, 2023
1 parent 6dade3c commit b38a327
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 3 deletions.
6 changes: 5 additions & 1 deletion packages/core/src/drivers/DatabaseDriver.ts
Expand Up @@ -187,9 +187,13 @@ export abstract class DatabaseDriver<C extends Connection> implements IDatabaseD
data[`${path.join('.')}.${sub.embedded![1]}`] = payload[sub.embedded![1]];
};

const parentPropName = kk.substring(0, kk.indexOf('.'));

// we might be using some native JSON operator, e.g. with mongodb's `$geoWithin` or `$exists`
if (props[kk]) {
inline(data[prop.name], props[kk], [prop.name]);
inline(data[prop.name], props[kk] || props[parentPropName], [prop.name]);
} else if (props[parentPropName]) {
data[`${prop.name}.${kk}` as keyof T] = data[prop.name][kk];
} else {
unknownProp = true;
}
Expand Down
6 changes: 4 additions & 2 deletions packages/core/src/utils/QueryHelper.ts
@@ -1,6 +1,6 @@
import { Reference } from '../entity/Reference';
import { Utils } from './Utils';
import type { Dictionary, EntityMetadata, EntityProperty, FilterDef, ObjectQuery, FilterQuery } from '../typings';
import type { Dictionary, EntityMetadata, EntityProperty, FilterDef, FilterQuery, ObjectQuery } from '../typings';
import { ARRAY_OPERATORS, GroupOperator, ReferenceType } from '../enums';
import type { Platform } from '../platforms';
import type { MetadataStorage } from '../metadata/MetadataStorage';
Expand Down Expand Up @@ -144,7 +144,9 @@ export class QueryHelper {
value = QueryHelper.processCustomType<T>(prop, value, platform, undefined, true);
}

if (prop?.customType instanceof JsonType && Utils.isPlainObject(value) && !platform.isRaw(value) && Object.keys(value)[0] !== '$eq') {
const isJsonProperty = prop?.customType instanceof JsonType && Utils.isPlainObject(value) && !platform.isRaw(value) && Object.keys(value)[0] !== '$eq';

if (isJsonProperty) {
return this.processJsonCondition(o, value, [prop.fieldNames[0]], platform, aliased);
}

Expand Down
81 changes: 81 additions & 0 deletions tests/issues/GH4755.test.ts
@@ -0,0 +1,81 @@
import { ObjectId } from 'bson';
import { Entity, PrimaryKey, Property, Embeddable, Embedded, wrap } from '@mikro-orm/core';
import { MikroORM } from '@mikro-orm/mongodb';
import { TsMorphMetadataProvider } from '@mikro-orm/reflection';

@Embeddable()
class ApiIpApiRequest {

@Property()
body?: Record<string, unknown>;

@Property()
headers?: Record<string, unknown>;

@Property()
method!: string;

@Property()
url!: string;

}

@Embeddable()
class ApiIpApiResponse {

@Property()
json?: Record<string, unknown>;

}

@Entity()
class ApiIpApi {

@PrimaryKey()
_id!: ObjectId;

@Embedded(() => ApiIpApiRequest, { object: true })
request?: ApiIpApiRequest;

@Embedded(() => ApiIpApiResponse, { object: true })
response?: ApiIpApiResponse;

}

let orm: MikroORM;

beforeAll(async () => {
orm = await MikroORM.init({
entities: [ApiIpApi],
clientUrl: 'mongodb://localhost:27017/mikro-orm-test-4755',
metadataProvider: TsMorphMetadataProvider,
cache: { enabled: false },
});
await orm.em.insert(ApiIpApi, {
request: {
body: { ip: '123.123.123', foo: 'bar', lol: true, num: 123 },
method: 'post',
url: 'url',
},
});
});

afterAll(() => orm.close(true));

test('GH #4755', async () => {
const foo = await orm.em.findOneOrFail(ApiIpApi, {
request: {
body: {
ip: '123.123.123',
},
},
});
expect(wrap(foo).toObject()).toEqual({
id: foo._id.toString(),
request: {
body: { ip: '123.123.123', foo: 'bar', lol: true, num: 123 },
method: 'post',
url: 'url',
},
});
});

0 comments on commit b38a327

Please sign in to comment.