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

Mongodb: When field is null in db, typeorm query sets it to undefined #7760

Closed
2 of 21 tasks
redjolr opened this issue Jun 17, 2021 · 8 comments · Fixed by #7820 or GulajavaMinistudio/typeorm#412
Closed
2 of 21 tasks

Comments

@redjolr
Copy link

redjolr commented Jun 17, 2021

Issue Description

When using TypeORM with MongoDB, you have the opportunity to set this decorator on a field:

@Column('string', { nullable: true, default: null })
nullableField: string | null;

When you query the collection, the returned documents that have a null value in the database, have the field value set to undefined.

Expected Behavior

The value of field in the queried documents should be set to null instead of undefined.

Actual Behavior

The value of field in the queried documents should is set to undefined instead of null.

Steps to Reproduce

  1. Create a mongodb collection schema
@Entity({ name: 'colletionname' })
export default class SomeEntity {
  @ObjectIdColumn({ name: '_id' })
  id: ObjectID;

  @Column('string', { nullable: true, default: null })
  nullableField: string | null;

  @Column()
  otherField: number;
}
  1. Insert in the database some documents that have their nullableField set to null:
    [{ nullableField: null, otherField: 1 }, { nullableField: null, otherField: 2 }]
  2. Create this file:
import {getRepository} from "typeorm";
import {UserRepository} from "./repository/UserRepository";

const someRepo = getRepository(SomeRepository);
const entity = someRepo
              .findOne({ otherField: 2 })
              .then((entity) => console.log(entity?.nullableField));
  1. In step 3, undefined will be printed instead of the expected null.

My Environment

Dependency Version
Operating System Ubuntu 20
Node.js version v14.15.5
Typescript version v4.2.3
TypeORM version v0.2.34

Additional Context

Relevant Database Driver(s)

  • aurora-data-api
  • aurora-data-api-pg
  • better-sqlite3
  • cockroachdb
  • cordova
  • expo
  • mongodb
  • mysql
  • nativescript
  • oracle
  • postgres
  • react-native
  • sap
  • sqlite
  • sqlite-abstract
  • sqljs
  • sqlserver

Are you willing to resolve this issue by submitting a Pull Request?

  • Yes, I have the time, and I know how to start.
  • Yes, I have the time, but I don't know how to start. I would need guidance.
  • No, I don't have the time, although I believe I could do it if I had the time...
  • No, I don't have the time and I wouldn't even know how to start.
@SnapeEye
Copy link
Contributor

Has the same issue.
In Robo 3T (MongoDB GUI) find query returns all the fields (including those with 'null' values).

But the TypeORM find just skips those fileds (the author wrote that it sets null values as undefined, but this is not quite correct).

Screenshot_1

@redjolr
Copy link
Author

redjolr commented Jun 18, 2021

@SnapeEye
Are you aware of any workarounds, or if the author intends to fix this?

@SnapeEye
Copy link
Contributor

SnapeEye commented Jun 18, 2021

@SnapeEye
Are you aware of any workarounds, or if the author intends to fix this?

Actually I don't know any workaround.

I've spent some time in typeorm code, researching this issue. Here what I can say:

  • Everething starts from the moment when mongo cursor is making array from the data (MongoEntityManager, toArray override is added in function applyEntityTransformationToCursor)
  • In that overrided toArray is used DocumentToEntityTransformer entity that call transformAll and make some stuff with our data
  • In transform function (called from transformAll in map) there is a forEach loop that choose which fields should be added (and which should be skipped, of couse).
  • In this loop I clearly see the filter for null and undefined values.

I believe that if you store null or undefined value in your DB - its quite ok. As for now - I don't see any problems, conflicts in it.
This issue requires only code fix.

Screenshot_2

UPDATE:
I tried to remove both checks (for null and undefined) and got expected response with all values from the DB.
Screenshot_3

@SnapeEye
Copy link
Contributor

Expected diff with changes (DocumentToEntityTransformer.ts):

    transform(document: any, metadata: EntityMetadata) {
        ...

        // get value from columns selections and put them into object
        metadata.ownColumns.forEach(column => {
            const valueInObject = document[column.databaseNameWithoutPrefixes];
-            if (valueInObject !== undefined &&
-                valueInObject !== null &&
-                column.propertyName &&
+           if (column.propertyName &&
                !column.isVirtual) {
                // const value = this.driver.prepareHydratedValue(valueInObject, column);

                entity[column.propertyName] = valueInObject;
                hasData = true;
            }
        });

    ...
    }

@imnotjames
Copy link
Contributor

I think it should still retain the strict undefined check, shouldn't it?

@SnapeEye
Copy link
Contributor

I think it should still retain the strict undefined check, shouldn't it?

I believe that it us very useful to get the whole entity model in response. And if some fields has undefined value, you can see it clearly and fix the issue (if it is required).

As for now, I don't see any negative points in undefined values. Maybe you know any potential issues that may raise if undefined check will be removed?

@imnotjames
Copy link
Contributor

I think it should still retain the strict undefined check, shouldn't it?

I believe that it us very useful to get the whole entity model in response. And if some fields has undefined value, you can see it clearly and fix the issue (if it is required).

As for now, I don't see any negative points in undefined values. Maybe you know any potential issues that may raise if undefined check will be removed?

undefined means it's just not there. I'm mostly suggesting this to cut down the amount of change that happens here.

@SnapeEye
Copy link
Contributor

undefined means it's just not there. I'm mostly suggesting this to cut down the amount of change that happens here.

'undefined' value may be set in response if user didn't set in in db. You can see this example above on screenshots (field barcode). This means that the field is declared in db entity but wasn't set in the document (by some reason - server error, missed the logic update, etc.) Actually, I've already facee this issue, thinking that everything is OK. But it wasn't because I didn't even see that undefined in my response. Quite tricky situation)

But if you suggest to keep this check - let's keep it. I think you should know better)

SnapeEye added a commit to SnapeEye/typeorm that referenced this issue Jun 30, 2021
…cuments

Find operation should add all nullable values from documents if they exist

Closes: typeorm#7760
imnotjames pushed a commit that referenced this issue Jun 30, 2021
…cuments (#7820)

Find operation should add all nullable values from documents if they exist

Closes: #7760
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants