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"});
答案 0 :(得分:10)
对于 2021 年发现此问题的任何人,Typeorm 的 Repository.save()
方法将在找到与主键匹配的情况下更新或插入。这也适用于 sqlite。
来自文档:
/**
* Saves all given entities in the database.
* If entities do not exist in the database then inserts, otherwise updates.
*/
答案 1 :(得分:9)
正如Tomer Amir所指出的,目前有真实upsert 的部分解决方案,并且功能请求是在TypeORM的存储库中打开的ATM:
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();
旧答案实际上指的是"更新"做OP所要求的方式:
已经有了一种方法:Repository<T>.save()
,其文档说明:
保存数据库中的所有给定实体。如果实体不存在 然后数据库插入,否则更新。
但是如果你没有指定id或唯一的字段集,那么save方法就不会知道你正在引用现有的数据库对象。
所以使用typeORM进行插播是:
let contraption = await thingRepository.save({id: 1, name : "New Contraption Name !"});
答案 2 :(得分:4)
对于正在寻找一种方法来向上添加多个记录并使用Postgres和TypeORM的任何人,您都可以通过exclude关键字访问您尝试更新/插入的行。
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();
答案 3 :(得分:2)
现在有a library插入TypeORM来帮助完成此任务。
答案 4 :(得分:2)
当ONCONFLICT
与MySQL不兼容时,这可能会有所帮助。来自Github
await getConnection()
.createQueryBuilder()
.insert()
.into(GroupEntity)
.values(updatedGroups)
.orUpdate({ conflict_target: ['id'], overwrite: ['name', 'parentId', 'web', 'avatar', 'description'] })
.execute();
答案 5 :(得分:1)
使用INSERT IGNORE忽略MySQL上的重复项:
await connection.createQueryBuilder()
.insert()
.into(Post)
.values(post)
.orIgnore()
.execute();
答案 6 :(得分:0)
在此处以用户身份登录您的实体
@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");
};
答案 7 :(得分:0)
对于那些在唯一约束冲突中挣扎的人,例如两个唯一字段,请执行此操作。
所以首先在你的实体中为约束添加一个名称,
@Entity()
@Unique('constraint_name', ['col_one', 'col_two'])
然后,您可以使用 onConflict 和 ON CONSTRAINT
this.createQueryBuilder()
.insert()
.into(YourEntity)
.values(yourValues)
.onConflict(`ON CONSTRAINT constraint_name DO UPDATE SET whatever = 1`)
.execute()
);
答案 8 :(得分:0)
您可能想要检查 Repository 类中的“预加载”方法:https://typeorm.delightful.studio/classes/repository_repository.repository.html#preload
<块引用>从给定的计划 javascript 对象创建一个新实体。如果实体已存在于数据库中,则加载它(以及与其相关的所有内容),用给定对象中的新值替换所有值并返回此新实体。这个新实体实际上是从 db 实体加载的,所有属性都从新对象中替换。请注意,给定的类实体对象必须具有实体 ID/主键才能查找实体。如果未找到具有给定 id 的实体,则返回 undefined。
如上所述,限制是您需要通过 ID 进行搜索。