TypeORM upsert - 如果不存在则创建
TypeORM upsert - create if not exist
TypeORM 是否包含一些功能来避免这种情况:
let contraption = await thingRepository.findOne({ name : "Contraption" });
if(!contraption) // Create if not exist
{
let newThing = new Thing();
newThing.name = "Contraption"
await thingRepository.save(newThing);
contraption = newThing;
}
类似于:
let contraption = await thingRepository.upsert({ name : "Contraption" });
正如Tomer Amir所指出的,目前有一个针对real upsert的部分解决方案,并且在TypeORM的存储库上打开了一个功能请求:
TypeORM upsert feature request
部分解决方案:
await connection.createQueryBuilder()
.insert()
.into(Post)
.values(post2)
.onConflict(`("id") DO NOTHING`)
.execute();
await connection.createQueryBuilder()
.insert()
.into(Post)
.values(post2)
.onConflict(`("id") DO UPDATE SET "title" = :title`)
.setParameter("title", post2.title)
.execute();
旧答案实际上指向 "update" 执行 OP 要求的方式:
已经有一个方法:Repository<T>.save()
,其中的文档说:
Saves all given entities in the database. If entities do not exist in
the database then inserts, otherwise updates.
但是如果您不指定 id 或唯一字段集,保存方法就无法知道您正在引用现有的数据库对象。
所以使用 typeORM 进行更新是:
let contraption = await thingRepository.save({id: 1, name : "New Contraption Name !"});
在此处以用户身份在您的实体中注明
@OneToMany(type => Post, post => post.user, {
cascade: true
})
posts: Post[];
export const saveAllPosts = async (req: Request, res: Response) => {
const userRepository = getManager().getRepository(User);
const postRepository = getManager().getRepository(Post);
let i;
let newUsers:any = [];
let newUser:any = {};
let newPost:any = {};
for(i=1; i<=6; i ++) {
newUser = await userRepository.findOne({
where: { id: i}
});
if(typeof newUser == "undefined") {
newUser = new User();
console.log("insert");
} else {
console.log("update");
}
newUser.name = "naval pankaj test"+i;
newPost = await postRepository.findOne({
where: { userId: i}
});
if(typeof newPost == "undefined") {
newPost = new Post();
console.log("post insert");
} else {
console.log("post update");
}
newPost.title = "naval pankaj add post title "+i;
newUser.posts = [newPost];
newUsers.push(newUser);
}
await userRepository.save(newUsers);
res.send("complete");
};
对于正在寻找更新插入多条记录并使用 Postgres 和 TypeORM 的任何人,您可以通过排除的关键字访问您尝试 update/insert 的行。
const posts = [{ id: 1, title: "First Post" }, { id: 2, title: "Second Post" }];
await connection.createQueryBuilder()
.insert()
.into(Post)
.values(posts)
.onConflict(`("id") DO UPDATE SET "title" = excluded."title"`)
.execute();
现在有 a library 插入 TypeORM 来帮助做到这一点。
使用 INSERT IGNORE 忽略 MySQL 和 Postgres 上的重复项:
await connection.createQueryBuilder()
.insert()
.into(Post)
.values(post)
.orIgnore()
.execute();
当 ONCONFLICT
不适用于 MySQL 时,这可能会有所帮助。来自 Github
await getConnection()
.createQueryBuilder()
.insert()
.into(GroupEntity)
.values(updatedGroups)
.orUpdate({ conflict_target: ['id'], overwrite: ['name', 'parentId', 'web', 'avatar', 'description'] })
.execute();
对于在 2021 年发现此问题的任何人,Typeorm 的 Repository.save()
方法将在找到与主键匹配的情况下进行更新或插入。这也适用于 sqlite。
来自文档:
/**
* Saves all given entities in the database.
* If entities do not exist in the database then inserts, otherwise updates.
*/
对于那些因唯一约束冲突而苦苦挣扎的人,例如两个唯一字段,请执行此操作。
因此,首先在您的实体中为约束添加一个名称,
@Entity()
@Unique('constraint_name', ['col_one', 'col_two'])
然后,你可以使用 onConflict with ON CONSTRAINT
this.createQueryBuilder()
.insert()
.into(YourEntity)
.values(yourValues)
.onConflict(`ON CONSTRAINT constraint_name DO UPDATE SET whatever = 1`)
.execute()
);
您可能想从存储库中检出“预加载”方法 class:https://typeorm.delightful.studio/classes/repository_repository.repository.html#preload
Creates a new entity from the given plan javascript object. If entity already exist in the database, then it loads it (and everything related to it), replaces all values with the new ones from the given object and returns this new entity. This new entity is actually a loaded from the db entity with all properties replaced from the new object. Note that given entity-like object must have an entity id / primary key to find entity by. Returns undefined if entity with given id was not found.
如上所说,限制是需要按ID搜索
2021 年答案:v0.2.40 为 TypeORM 添加了原生更新插入支持
TypeORM 是否包含一些功能来避免这种情况:
let contraption = await thingRepository.findOne({ name : "Contraption" });
if(!contraption) // Create if not exist
{
let newThing = new Thing();
newThing.name = "Contraption"
await thingRepository.save(newThing);
contraption = newThing;
}
类似于:
let contraption = await thingRepository.upsert({ name : "Contraption" });
正如Tomer Amir所指出的,目前有一个针对real upsert的部分解决方案,并且在TypeORM的存储库上打开了一个功能请求:
TypeORM upsert feature request
部分解决方案:
await connection.createQueryBuilder()
.insert()
.into(Post)
.values(post2)
.onConflict(`("id") DO NOTHING`)
.execute();
await connection.createQueryBuilder()
.insert()
.into(Post)
.values(post2)
.onConflict(`("id") DO UPDATE SET "title" = :title`)
.setParameter("title", post2.title)
.execute();
旧答案实际上指向 "update" 执行 OP 要求的方式:
已经有一个方法:Repository<T>.save()
,其中的文档说:
Saves all given entities in the database. If entities do not exist in the database then inserts, otherwise updates.
但是如果您不指定 id 或唯一字段集,保存方法就无法知道您正在引用现有的数据库对象。
所以使用 typeORM 进行更新是:
let contraption = await thingRepository.save({id: 1, name : "New Contraption Name !"});
在此处以用户身份在您的实体中注明
@OneToMany(type => Post, post => post.user, {
cascade: true
})
posts: Post[];
export const saveAllPosts = async (req: Request, res: Response) => {
const userRepository = getManager().getRepository(User);
const postRepository = getManager().getRepository(Post);
let i;
let newUsers:any = [];
let newUser:any = {};
let newPost:any = {};
for(i=1; i<=6; i ++) {
newUser = await userRepository.findOne({
where: { id: i}
});
if(typeof newUser == "undefined") {
newUser = new User();
console.log("insert");
} else {
console.log("update");
}
newUser.name = "naval pankaj test"+i;
newPost = await postRepository.findOne({
where: { userId: i}
});
if(typeof newPost == "undefined") {
newPost = new Post();
console.log("post insert");
} else {
console.log("post update");
}
newPost.title = "naval pankaj add post title "+i;
newUser.posts = [newPost];
newUsers.push(newUser);
}
await userRepository.save(newUsers);
res.send("complete");
};
对于正在寻找更新插入多条记录并使用 Postgres 和 TypeORM 的任何人,您可以通过排除的关键字访问您尝试 update/insert 的行。
const posts = [{ id: 1, title: "First Post" }, { id: 2, title: "Second Post" }];
await connection.createQueryBuilder()
.insert()
.into(Post)
.values(posts)
.onConflict(`("id") DO UPDATE SET "title" = excluded."title"`)
.execute();
现在有 a library 插入 TypeORM 来帮助做到这一点。
使用 INSERT IGNORE 忽略 MySQL 和 Postgres 上的重复项:
await connection.createQueryBuilder()
.insert()
.into(Post)
.values(post)
.orIgnore()
.execute();
当 ONCONFLICT
不适用于 MySQL 时,这可能会有所帮助。来自 Github
await getConnection()
.createQueryBuilder()
.insert()
.into(GroupEntity)
.values(updatedGroups)
.orUpdate({ conflict_target: ['id'], overwrite: ['name', 'parentId', 'web', 'avatar', 'description'] })
.execute();
对于在 2021 年发现此问题的任何人,Typeorm 的 Repository.save()
方法将在找到与主键匹配的情况下进行更新或插入。这也适用于 sqlite。
来自文档:
/**
* Saves all given entities in the database.
* If entities do not exist in the database then inserts, otherwise updates.
*/
对于那些因唯一约束冲突而苦苦挣扎的人,例如两个唯一字段,请执行此操作。
因此,首先在您的实体中为约束添加一个名称,
@Entity()
@Unique('constraint_name', ['col_one', 'col_two'])
然后,你可以使用 onConflict with ON CONSTRAINT
this.createQueryBuilder()
.insert()
.into(YourEntity)
.values(yourValues)
.onConflict(`ON CONSTRAINT constraint_name DO UPDATE SET whatever = 1`)
.execute()
);
您可能想从存储库中检出“预加载”方法 class:https://typeorm.delightful.studio/classes/repository_repository.repository.html#preload
Creates a new entity from the given plan javascript object. If entity already exist in the database, then it loads it (and everything related to it), replaces all values with the new ones from the given object and returns this new entity. This new entity is actually a loaded from the db entity with all properties replaced from the new object. Note that given entity-like object must have an entity id / primary key to find entity by. Returns undefined if entity with given id was not found.
如上所说,限制是需要按ID搜索
2021 年答案:v0.2.40 为 TypeORM 添加了原生更新插入支持