Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent Single Parameter Search Behavior with "Record<string, unknown>" type #4755

Closed
devcaeg opened this issue Sep 27, 2023 · 3 comments
Labels
bug Something isn't working

Comments

@devcaeg
Copy link

devcaeg commented Sep 27, 2023

Describe the bug
There's an issue with the search functions in MikroOrm. When a parameter is of type "Record<string, unknown>", the database search demands an exact object match, rather than allowing searches based on a single parameter.

Example

@Embeddable()
export class ApiIpApiRequest {
  @Property()
  body?: Record<string, unknown>;

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

  @Property()
  method!: string;

  @Property()
  url!: string;
}

@Embeddable()
export class ApiIpApiResponse {
  @Property()
  json?: Record<string, unknown>;
}

@Entity({
  collection: 'api_ipapi',
})
export class ApiIpApi extends Base {
  @Enum({
    items: () => ApiIpApiActions,
  })
  action!: ApiIpApiActions;

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

  @Embedded({
    object: true,
  })
  response?: ApiIpApiResponse;
}
await this.apiIpApiRepository.findOne({
  createdAt: {
    $gte: new Date(Date.now() - 1000 * 60 * 60 * 6),
  },
  request: {
    body: {
      ip: '123.123.123',
    },
  },
});

If there's a document in the database with its only saved field coming from "request.body" being the "ip" parameter, and the search is based solely on matches for "request.body.ip", then the result is successful. However, if "request.body" has multiple parameters and the search is limited to finding matches in "request.body.ip", it will always return "null", even if there is a document with that specific "ip" in the database. Essentially, when the parameter type is "Record<string, unknown>", MikroOrm, for some reason, expects the search to match entirely with the stored document, preventing searches based on a single parameter.

It's worth noting that if all the data in "request.body" were typed, either through an "object" or an "Embeddable", then it would be possible to search using just one parameter.

Expected behavior
It's expected that even if a parameter is of type "Record<string, unknown>", one should be able to search the database based on a single parameter rather than requiring an exact object match.

Additional context
I'm using the Mongo driver and version 6 of MikroOrm; however, the same issue occurs in version 5.

Versions

Dependency Version
node 20.5.1
typescript 5.2.2
mikro-orm 6.0.0-dev.106
mikro-orm/mongodb 6.0.0-dev.106
nestjs 10.2.6
@B4nan
Copy link
Member

B4nan commented Sep 27, 2023

What if you type it this way?

@Property({ type: 'json' })
body?: Record<string, unknown>;

I guess you are using ts-morph?

@devcaeg
Copy link
Author

devcaeg commented Sep 27, 2023

What if you type it this way?

@Property({ type: 'json' })
body?: Record<string, unknown>;

I guess you are using ts-morph?

When adding "@Property({ type: 'json' })", the issue worsens, as the search returns "null" even when "request.body" only contains the "ip" parameter. However, using just "@Property()", I get a positive result if "request.body" has only one parameter in the database; but if there's more than one, it doesn't return any result.

In summary, with only "@Property()" the behavior is bad, but with "@Property({ type: 'json' })" it deteriorates even further.

It's important to note that I'm using the "TsMorphMetadataProvider" for metadata provisioning.

@devcaeg
Copy link
Author

devcaeg commented Sep 27, 2023

{
  "properties": {
    "body": {
      "name": "body",
      "kind": "scalar",
      "getter": false,
      "setter": false,
      "type": "Record<string, unknown>",
      "array": false,
      "runtimeType": "Record<string, unknown>",
      "optional": true
    },
    "headers": {
      "name": "headers",
      "kind": "scalar",
      "getter": false,
      "setter": false,
      "type": "Record<string, unknown>",
      "array": false,
      "runtimeType": "Record<string, unknown>",
      "optional": true
    },
    "method": {
      "name": "method",
      "kind": "scalar",
      "getter": false,
      "setter": false,
      "type": "string",
      "array": false,
      "runtimeType": "string"
    },
    "url": {
      "name": "url",
      "kind": "scalar",
      "getter": false,
      "setter": false,
      "type": "string",
      "array": false,
      "runtimeType": "string"
    }
  },
  "props": [
    {
      "name": "body",
      "kind": "scalar",
      "getter": false,
      "setter": false,
      "type": "Record<string, unknown>",
      "array": false,
      "runtimeType": "Record<string, unknown>",
      "optional": true
    },
    {
      "name": "headers",
      "kind": "scalar",
      "getter": false,
      "setter": false,
      "type": "Record<string, unknown>",
      "array": false,
      "runtimeType": "Record<string, unknown>",
      "optional": true
    },
    {
      "name": "method",
      "kind": "scalar",
      "getter": false,
      "setter": false,
      "type": "string",
      "array": false,
      "runtimeType": "string"
    },
    {
      "name": "url",
      "kind": "scalar",
      "getter": false,
      "setter": false,
      "type": "string",
      "array": false,
      "runtimeType": "string"
    }
  ]
}

Here's a summary of the JSON generated in the "temp" folder. The file is named "ApiIpApiRequest.js.json". I hope this information proves helpful.

Note: This is the JSON generated using "@Property()".

@B4nan B4nan added the bug Something isn't working label Sep 29, 2023
@B4nan B4nan closed this as completed in b38a327 Sep 30, 2023
B4nan added a commit that referenced this issue Sep 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants