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

Upsert implementation #367

Closed
ramiel opened this issue Feb 26, 2020 · 10 comments
Closed

Upsert implementation #367

ramiel opened this issue Feb 26, 2020 · 10 comments
Labels
enhancement New feature or request

Comments

@ramiel
Copy link

ramiel commented Feb 26, 2020

Is your feature request related to a problem? Please describe.
A clarification on a possible feature

I'm going to create a CustomBaseRepository to implement a generic method to find or create (upsert). Can you point me to some example on how to create such a base repository? The documentation (https://mikro-orm.io/docs/repositories#custom-repository) si not very exhaustive and the links provided have no example for a custom base repository.

Alternatively, does such method exist already?

@ramiel ramiel added the enhancement New feature or request label Feb 26, 2020
@B4nan
Copy link
Member

B4nan commented Feb 26, 2020

Just create a generic class extending EntityRepository and pass it in the ORM config via MikroORM.init({ entityRepository: CustomBaseRepository }).

Something like this should work:

export class CustomBaseRepository<T extends AnyEntity<T>> extends EntityRepository<T> {
  upsert() { ... }
}

Alternatively, does such method exist already?

Nope.

Not sure if I understood well, do you also need help with implementation of the upsert method? Should be quite trivial.

@ramiel
Copy link
Author

ramiel commented Feb 26, 2020

Thanks, it's perfect. No, I don't need help with the implementation but I need to understand about the internals of the EntityRepository, but for that I can check the source code. Thank you again

@B4nan
Copy link
Member

B4nan commented Feb 26, 2020

Its pretty simple, all what repository does is that it forwards calls to the entity manager with the entity name stored in this.entityName. But you can use the repository methods directly so it will be handled for you:

async upsert(data, where) {
  let e = await this.findOne(where);

  if (e) {
    wrap(e).assign(data);
  } else {
    e = this.create(data);
  }

  await this.persistAndFlush(e); // or maybe you do not want to flush here, depends on the use case

  return e;
}

@ramiel
Copy link
Author

ramiel commented Feb 26, 2020

Oh, is there a way to take advantage of upsert in mongo? I know it would be specific for only one DB, but it would run in a transaction. Otherwise I don't know if multiple operations like reading/writing can happen in transaction on MongoDB.
To clarify, I'd like to use mongo specific method findOneAndUpdate(where, updates, {upsert: true})

@B4nan
Copy link
Member

B4nan commented Feb 26, 2020

You can access the driver/connection and run methods on the native collection wrapper too:

// @ts-ignore
const collection = (this.em as EntityManager<MongoDriver>).getConnection().getCollection(this.entityName);
await collection.findOneAndUpdate(where, updates, {upsert: true});

But looking at the code, em is defined as private - will fix that to protected so you can do this without the @ts-ignore hint.

@ramiel
Copy link
Author

ramiel commented Feb 26, 2020

Perfect, thanks!

@B4nan
Copy link
Member

B4nan commented Feb 26, 2020

em is now protected in v3.3.2

@ramiel
Copy link
Author

ramiel commented Feb 27, 2020

Fast and cool, thanks!

@B4nan
Copy link
Member

B4nan commented Feb 27, 2020

Can we close this now?

@ramiel
Copy link
Author

ramiel commented Feb 27, 2020

Yes, sure, I'm closing it

@ramiel ramiel closed this as completed Feb 27, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants