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

How about supporting Raw result and join query? #68

Closed
yearsalary opened this issue Oct 31, 2022 · 8 comments
Closed

How about supporting Raw result and join query? #68

yearsalary opened this issue Oct 31, 2022 · 8 comments

Comments

@yearsalary
Copy link

example:

const queryBuilder = this.dataSource .createQueryBuilder(Notification, 'notification') .select('notification.id', 'id') .addSelect('message.title', 'title') .leftJoin('notification.receiver', 'user') .leftJoin('notification.message', 'message') .where('user.did =:did', { did: userDID }); const paginator = buildPaginator({ entity: Notification, paginationKeys: ['id'], query: pagingQuery, }); const { data, cursor } = await paginator.paginateRaw(queryBuilder); return { data, cursor };

@yearsalary yearsalary changed the title How about supporting Raw and join query How about supporting Raw and join query? Oct 31, 2022
@yearsalary
Copy link
Author

yearsalary commented Oct 31, 2022

and,,, typeorm querybuilder.take method is not working if with join query
typeorm/typeorm#4742

@yearsalary yearsalary changed the title How about supporting Raw and join query? How about supporting Raw result and join query? Oct 31, 2022
@benjamin658
Copy link
Owner

Sorry, I don’t get it, could you please explain it more?

@yearsalary
Copy link
Author

Sorry, I don’t get it, could you please explain it more?

ok,
In typeorm, to getting raw result use getRawMany method. (https://typeorm.io/select-query-builder#getting-raw-results)
In this package, Paginater.paginate method call getMany in typeorm to find entities.
To not only support entities but also raw result, add Paginater.paginateRaw and call getRawMany.

@benjamin658
Copy link
Owner

But if it returns raw results, then the library cannot generate cursors.

@yearsalary
Copy link
Author

yearsalary commented Nov 15, 2022

yes, so how about add paginateRaw that return generate cursor like paginate in your package like this.

public async paginateRaw(builder: SelectQueryBuilder<Entity>): Promise<PagingRawResult> {
        const raws = await this.appendPagingQuery(builder).getRawMany();
        const hasMore = raws.length > this.limit;

        if (hasMore) {
            raws.splice(raws.length - 1, 1);
        }

        if (raws.length === 0) {
            return this.toPagingResult(raws);
        }

        if (!this.hasAfterCursor() && this.hasBeforeCursor()) {
            raws.reverse();
        }

        if (this.hasBeforeCursor() || hasMore) {
            this.nextAfterCursor = this.encode(raws[raws.length - 1]);
        }

        if (this.hasAfterCursor() || (hasMore && this.hasBeforeCursor())) {
            this.nextBeforeCursor = this.encode(raws[0]);
        }

        return this.toPagingRawResult(raws);
    } 
   
private toPagingRawResult(raws: any[]): PagingRawResult {
        return {
            data: raws,
            cursor: this.getCursor(),
        };
    }    

this paginateRaw method logic equal paginate in your package except below code.

        const raws = await this.appendPagingQuery(builder).getRawMany();

@benjamin658
Copy link
Owner

Would you mind sending a PR for this feature with proper test cases?

@amiryadid-fb
Copy link

I've had this need as well so I had to implement myself, and I can tell it's not easy to do with typeorm, the mapping from raw results to entity results for cursor creation is tedious.
About JOIN queries, that just requires adding code to handle these cases as the number of results in page will be inconsistent when used with limit and offset.

@artekr
Copy link

artekr commented Oct 6, 2023

For solving the join query, I notice Typeorm provides this Joining and mapping functionality.
So in your case where you want to load the message:
.leftJoin('notification.message', 'message')
can be written to
.leftJoinAndMapOne('notification.message', 'notification.message', 'message')

In this case the Message entity will be loaded in the PagingResulst

NotificationEntity {
  id: '123',
  ...
  message: MessageEntity {
    id: '123'
    ...
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants