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
[Feature Request] Upsert generation #2363
Comments
does it work for you? |
Hi @pleerock Currently trying to work around it |
Try this: const updateQb = connection.createQueryBuilder().update(Model, model).where({
uniqueField: someValue
});
await connenction.createQueryBuilder()
.insert()
.into(Model)
.values(model)
.onConflict(updateQb.getQuery())
.setParameters(updateQb.getParameters())
.execute(); not sure, maybe you'll need to set native parameters as well. |
I did it, but the parameters are not ordered the same in both queries.. |
any news? |
What is your proposal? |
something like |
Seems like onConflict method not working for mysql. Can you please add support for mysql as well? |
EDIT The below solution still has problems. Namely, the update query and the insert query sort column names differently and therefore, values passed through end up not lining up properly for the update query. Original Comment: See this example to understand what I did to make it work. It's dirty, and would be nice if supported directly in typeorm. // Model.ts
@Entity()
class User {
@PrimaryColumn({ type: 'uuid' })
id: string
@Column()
firstName: string
@Column()
lastName: string
@Column()
age: number
} // Wherever you're doing your query
const newUser = {
id: uuidv4(), // let's assume this was passed
// in from client and might be dupe
firstName: 'bob',
lastName: 'bobberson',
age: 38,
}
const newUserSansId = {
firstName: 'bob',
lastName: 'bobberson',
age: 38,
}
const updateQb = connection
.createQueryBuilder()
.update(User, newUserSansId)
await connection
.createQueryBuilder()
.insert()
.into(User)
.values(newUser)
.onConflict(
`(id) DO ${updateQb
.getQuery()
// Update the beginning of the statement. Normal updates start slightly
// differently than ON CONFLICT DO UPDATE
.replace(/^UPDATE "users"/i, 'UPDATE')
// Update the parameter numbers. (increment by one to skip the id param)
.replace(
/\$(\d{1,2})/g,
(wholeMatch, numberMatch) =>
`$${Number.parseInt(numberMatch, 10) + 1}`,
)}`,
)
.setParameters(updateQb.getParameters())
.execute() INSERT INTO "users" ("id", "firstName", "lastName", "age")
VALUES ($1, $2, $3, $4)
ON CONFLICT (id)
DO
UPDATE
SET
"firstName" = $2,
"lastName" = $3,
"age" = $4
RETURNING
"id",
"firstName",
"lastName",
"age"; Additional Information: So, for instance, version columns are busted in on conflict updates because the reference is ambigious:
vs:
Also, no where clause exists in my above example because the update only looks at the conflicting row. You can put a where clause if needed, but in my above example it is not needed. |
Seems like a lot of unnecessary workarounds when a simple upsert method would solve everything. |
Yes TypeORM needs an upsert function. For anyone in need of an upsert() function for PostgreSQL, here's the one I wrote
https://gist.github.com/JeremyBernier/5683ebc8e83990a4d4e3d0abd1a9549d |
This adds EntityManager#upsert, BaseEntity#upsert and EntityManager#upsert Closes: typeorm#2363
This adds EntityManager#upsert, BaseEntity#upsert and EntityManager#upsert Closes: typeorm#2363
This adds EntityManager#upsert, Repository#upsert and BaseEntity.upsert Closes: typeorm#2363
This adds EntityManager#upsert, BaseEntity#upsert and EntityManager#upsert Closes: typeorm#2363
Hello. The @pleerock suggestion would be very useful. Unfortunately I cannot do it with mysql. Upsert is much faster for massive inserts. It's avoid to run multiples queries to do one atomic operation. For my scenario I have to run a native query as follow bellow, the results of entire process were 3 times faster than using typeorm multiples queries: const query = However we know that get into native queries aren't so good when the entities have to update. So any news on upsert with query builder for mysql in typeorm? |
* feat: add upsert methods for the drivers that support it This adds EntityManager#upsert, BaseEntity#upsert and EntityManager#upsert Closes: #2363 * docs: Document which drivers support upsert operations * docs: fix typo in entity manager upsert many example * refactor: remove mongodb style upsert signature, enforce types of conflict paths * docs: add note to repository docs specifying which drivers support upsert * refactor: cannot staticly type conflict paths because that would break typescript pre-4 * refactor: remove test utility methods in favor of some repeated checks
For everyone that can't upgrade anytime soon. I found this function to work pretty well for my needs.
|
…rm#8104) * feat: add upsert methods for the drivers that support it This adds EntityManager#upsert, BaseEntity#upsert and EntityManager#upsert Closes: typeorm#2363 * docs: Document which drivers support upsert operations * docs: fix typo in entity manager upsert many example * refactor: remove mongodb style upsert signature, enforce types of conflict paths * docs: add note to repository docs specifying which drivers support upsert * refactor: cannot staticly type conflict paths because that would break typescript pre-4 * refactor: remove test utility methods in favor of some repeated checks
Issue type:
[ ] question
[ ] bug report
[x] feature request
[ ] documentation issue
Database system/driver:
[ ]
cordova
[ ]
mongodb
[ ]
mssql
[ ]
mysql
/mariadb
[ ]
oracle
[x]
postgres
[ ]
sqlite
[ ]
sqljs
[ ]
react-native
TypeORM version:
[x]
latest
[ ]
@next
[ ]
0.x.x
(or put your version here)Steps to reproduce or a small repository showing the problem:
Hi,
I am trying to do an
upsert
to a large object and I am having trouble.I saw #1090 but this solution is not very good for me.
to upsert I need to build my query with
createQueryBuilder
butonConflict
only excepts string queries, which makes it very difficult with large objects since I have to write my query manually.Here is what I tied to do:
I think that having a function that if the insert fails just updates the whole object would be better.
is there any way to generate the
onConflict
query that I am missing?Thanks!
The text was updated successfully, but these errors were encountered: