TypeORM: update item and return it

笑着哭i 提交于 2020-12-30 04:55:39

问题


As far as I know, it's a best practice to return an item after it has been updated. TypeORM's updateById returns void, not the updated item though.

My question: Is it possible to update and return the modified item in a single line?

What I tried so far:

await this.taskRepository.updateById(id, { state, dueDate });
return this.taskRepository.findOne({ id });

What I'm looking for:

return this.taskRepository.updateById(id, { state, dueDate }); // returns updated task

回答1:


I just found out that I can do this with the .save method:

return this.taskRepository.save({
    id: task.id,
    state,
    dueDate
});

According to the docs (section save), partial updates are supported as well:

Also supports partial updating since all undefined properties are skipped.




回答2:


To expand on sandrooco's answer, this is what I do:

const property = await this.propertyRepository.findOne({
  where: { id }
});

return this.propertyRepository.save({
  ...property, // existing fields
  ...updatePropertyDto // updated fields
});



回答3:


Although I want await Table.update({}, {}) to return Table it doesn't. I've found it easier to just work with the QueryBuilder because it gives me more control in general, BUT if you don't like the QueryBuilder or don't need it, you can do something like this:

const post = await Post.update({id}, {...input}).then(response => response.raw[0]);
return post; // returns post of type Post

If you however do want to use QueryBuilder I suggest going with an approach like below. Others above has mentioned the usage of Repository and Table.save() Which doesn't really return the original type anywhere, so that approach is out of the picture for me.

An example of QueryBuilder and Table.update({}, {}):

@Mutation(() => PostResponse, { nullable: true })
@UseMiddleware(isAuthorized)
async updatePost(
  @Arg("id", () => Int) id: number,
  @Arg("input") input: PostInput,
  @Ctx() { req }: Context
): Promise<PostResponse | null> {

  const { userId } = req.session;
  const errors = validatePost(userId, ...input, await Post.findOne(id));

  if (errors) {
    return { errors };
  }

  const post = await Post.update({id}, {...input}).then(response => response.raw[0]);
  // OR
  const post = await getConnection()
    .createQueryBuilder()
    .update(Post)
    .set({ ...input })
    .where('id = :id and "creatorId" = :creatorId', {
      id,
      creatorId: userId,
    })
    .returning("*")
    .execute()
    .then((response) => {
      return response.raw[0];
    });

  return { post };
}

The key is returning response.raw[0] in order to get the type back.


I've abstracted the results into a Response class, that is why I return different things here. Added for clarity

@ObjectType()
class FieldError {
  @Field()
  field!: string;
  @Field()
  message!: string;
}

@ObjectType()
export class PostResponse {
  @Field(() => [FieldError], { nullable: true })
  errors?: FieldError[];

  @Field(() => Post, { nullable: true })
  post?: Post;
}

Note: I'm using TypeORM and Type-GraphQL here.

.returning("*") does not work on MySQL, see comments below.




回答4:


One way is to perform the update and then do a find based on the condition you specified



来源:https://stackoverflow.com/questions/47792808/typeorm-update-item-and-return-it

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!