Skip to content
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

find with relations returns soft-deleted entities #6265

Closed
Ollie1700 opened this issue Jun 16, 2020 · 25 comments · Fixed by mattwelke/typeorm-postgres-example#165 or newerton/gobarber-2-backend#17

Comments

@Ollie1700
Copy link

Issue type:

[x] question
[ ] bug report
[ ] feature request
[ ] documentation issue

Database system/driver:

[ ] cordova
[ ] mongodb
[ ] mssql
[ ] mysql / mariadb
[ ] oracle
[x] postgres
[ ] cockroachdb
[ ] sqlite
[ ] sqljs
[ ] react-native
[ ] expo

TypeORM version:

[x] latest
[ ] @next
[ ] 0.x.x (or put your version here)

Steps to reproduce or a small repository showing the problem:

Apologies for opening an issue for this, it seems like I am probably missing something very obvious but essentially the issue is that soft-deleted entities are being returned as part of relations.

Example:

Say we have "User" and "Post" - user has many posts

  1. const userWithPosts = await userRepo.findOne(1, { relations: [ 'posts' ] })
  2. userWithPosts.posts will contain all posts, even ones that have been deleted

Am I missing something obvious here? This functionality works as expected when not using relations (e.g. in the above example, postRepo.find() would only return non-deleted items) but when using relations I am running into this issue.

@Ollie1700
Copy link
Author

This behaviour is still a blocker for me at the moment. I'm wondering if anyone knows if it is intended, and if so what is the workaround? Or if it is known to be a bug I can look to make a PR for this one if someone can point me in the right direction.

Thanks again, I know your team must be very busy.

@andreimc
Copy link

andreimc commented Jul 1, 2020

@Ollie1700 we are seeing the same thing

@yorickdevries
Copy link

Same as #5838

@chenfanggm
Copy link

Same here.

@nshCore
Copy link

nshCore commented Oct 25, 2020

@Ollie1700 @chenfanggm is the field you use the @DeleteDateColumn() named 'deletedAt'?

Anything else wont work.

@chenfanggm
Copy link

chenfanggm commented Oct 26, 2020

@nshCore

@Ollie1700 @chenfanggm is the field you use the @DeleteDateColumn() named 'deletedAt'?

Anything else wont work.

Yea, I have named the @DeleteDateColumn() as deletedAt.
`@ObjectType()
export abstract class BaseEntity extends TypeormBaseEntity {
@field()
@CreateDateColumn({ type: 'timestamp with time zone' })
createdAt: Date;

@field()
@UpdateDateColumn({ type: 'timestamp with time zone' })
updatedAt: Date;

@field()
@DeleteDateColumn({ type: 'timestamp with time zone' })
deletedAt: Date;
}`

const post = await Post.findOne(id, { relations: [ 'creator', 'category', 'tags', 'threads', 'threads.creator', 'threads.replies', 'threads.replies.creator', 'threads.replies.replyToUser', ], order: { updatedAt: 'DESC', }, });

Even my thead is softDeleted, but it still come back as result for the query.

Thanks.

@marcinja
Copy link

marcinja commented Nov 4, 2020

I'm seeing a similar issue and also am using a column named `deletedAt

@riskidan
Copy link

riskidan commented Nov 9, 2020

Seeing the same problem

@KevinArce98
Copy link

Same problem, some solution?

@nebkat
Copy link
Contributor

nebkat commented Nov 27, 2020

This is simply because the functionality is not implemented. The code that normally adds the filter for deleted items is here, and it does so for the main entity in the query only, not for the relations:

const metadata = this.expressionMap.mainAlias!.metadata;
// Adds the global condition of "non-deleted" for the entity with delete date columns in select query.
if (this.expressionMap.queryType === "select" && !this.expressionMap.withDeleted && metadata.deleteDateColumn) {
const column = this.expressionMap.aliasNamePrefixingEnabled
? this.expressionMap.mainAlias!.name + "." + metadata.deleteDateColumn.propertyName
: metadata.deleteDateColumn.propertyName;
const condition = `${this.replacePropertyNames(column)} IS NULL`;
conditionsArray.push(condition);
}

It makes sense to filter out deleted One-to-Many/Many-to-Many relations, but it might not be the expected default behavior for a One-to-One/Many-to-One relation. If a user's "profile" has been deleted, you might still expect the relation to be loaded, especially if user.profile can't be null.

If someone wants to implement an option for this you can send in a PR and link to this issue, it shouldn't be too difficult. Start with SelectQueryBuilder and QueryBuilder.


BTW, please avoid commenting just to say you have the problem. The original issue has described what is wrong, unless you have something useful to add just 👍 it.

@klaaz0r
Copy link

klaaz0r commented Jan 16, 2021

What is the status of this? Seems like a fundamental feature to have would like to work on it but is anyone already fixing this?

@nebkat
Copy link
Contributor

nebkat commented Jan 16, 2021

I am not aware of anyone working on this, you can submit a PR if you want.

luiseariass pushed a commit to luiseariass/typeorm that referenced this issue Jan 19, 2021
…ties

This new feature changes the behavior of typeorm to allow avoiding entities that have soft delete
close: typeorm#6265
luiseariass added a commit to luiseariass/typeorm that referenced this issue Jan 19, 2021
…ties

This new feature changes the behavior of typeorm to allow avoiding entities that have soft delete
close: typeorm#6265
luiseariass added a commit to luiseariass/typeorm that referenced this issue Jan 19, 2021
…ties

This new feature changes the behavior of typeorm to allow avoiding entities that have soft delete
close: typeorm#6265
@jdnielss
Copy link

Seeing the same problem

luiseariass added a commit to luiseariass/typeorm that referenced this issue Jan 20, 2021
…ties

This new feature changes the behavior of typeorm to allow avoiding entities that have soft delete
close: typeorm#6265
luiseariass added a commit to luiseariass/typeorm that referenced this issue Jan 20, 2021
…ties

This new feature changes the behavior of typeorm to allow avoiding entities that have soft delete
close: typeorm#6265
luiseariass added a commit to luiseariass/typeorm that referenced this issue Jan 20, 2021
…ties

This new feature changes the behavior of typeorm to allow avoiding entities that have soft delete
close: typeorm#6265
@lorenzosignoretti
Copy link

I know the issue has been closed, but I think the behaviour has remained the same even in 0.2.31

@klaaz0r
Copy link

klaaz0r commented Jul 7, 2021

@lorenzosignoretti exactly the same ting happening for me, it can be related with the skip/limit I also include maybe?

@mossa-Sammer
Copy link

it's not working neither using find options nor query builder, it's frustrating that I need to write a query with 6 joins manually :(

@mossa-Sammer
Copy link

mossa-Sammer commented Jul 27, 2021

Worked for me when using the query builder and placing the withDeleted function at the top like this

orderRepo
      .createQueryBuilder('order')
      .withDeleted()
      .innerJoin('order.kitchen', 'kitchen')
      .innerJoin('order.user', 'user')
      .innerJoin('order.orderStatus', 'orderStatus')
      .leftJoin('order.orderStatusLogs', 'orderStatusLogs')
      .innerJoinAndSelect('order.orderItems', 'orderItems')
      .leftJoinAndSelect('orderItems.foodListing', 'foodListing')
      .where('order.order_id = :orderId', { orderId })
      .getOne();

but still not working with find options

@xerxes235
Copy link

in most cases, you have to use innerJoinAndSelect instead of leftJoinAndSelect.

@tuananhlai
Copy link

Is there any workaround for this issue? It seems weird that such a basic feature is missing.

@EdsonRCJ
Copy link

Is there any update for this issue ? I'm facing the same.

@ryanhex53
Copy link

But I want the ManyToOne relation being loaded even it was soft-deleted, it returns null in version 0.2.45. How can I do ?

@ryanhex53
Copy link

But I want the ManyToOne relation being loaded even it was soft-deleted, it returns null in version 0.2.45. How can I do ?

For someone who need load soft-deleted relations, this is my approach.

async listAll(
  dto: PageableDto,
  where?: FindConditions<T>[] | string | ObjectLiteral,
  relations?: string[],
  select?: any[]
): Promise<PaginatedRes<T>> {
  where = where || {};
  const total = await this.repo.count({ where });
  const order: any = dto.by && dto.sort ? { [dto.by]: dto.sort } : {};
  // fix *where* to exclude soft-deleted
  if (Array.isArray(where)) {
    where.forEach((cond: ObjectLiteral) => {
      cond.deletedDate = IsNull();
    });
  } else if (typeof where != 'string') {
    where.deletedDate = IsNull();
  }
  const options: FindManyOptions<T> = {
    withDeleted: true, // force load relations include soft-deleted
    where,
    relations,
    select,
    order
  };
  if (dto.limit != -1) {
    options.take = dto.limit;
    options.skip = (dto.page - 1) * dto.limit;
  }
  const results = await this.repo.find(options);
  const pages = dto.limit == -1 ? 1 : Math.ceil(total / dto.limit);
  return {
    results,
    page: dto.page,
    pages,
    limit: dto.limit,
    total
  };
}

@kevin4dhd
Copy link

any solution? :/

@osellas
Copy link

osellas commented Sep 15, 2023

Same here 😬

@amiralammohawk
Copy link

same

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment