TypeORM upsert - 如果不存在则创建

时间:2017-10-14 14:33:50

标签: typescript 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"});

9 个答案:

答案 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 进行搜索。