2
\$\begingroup\$

Can you guys review my GraphQL search pagination function? I'm afraid there could be some performance issues, or something. Especially at the aggregation section and this const result: any = await this.BooksModel.findOne( section.

I'm using MongoDB as the database and string ISO Date as cursor.

I tried looking for any search pagination example on the internet but found none.

async getBooks({
    first,
    after,
    last,
    before,
    search,
}: {
    first?: number | null
    after?: string | null
    last?: number | null
    before?: string | null
    search?: string | null
}) {
    if (first && last)
        throw new AppError(
            '`first` and `last` cannot be used at the same time',
            400,
        )
    if (!first && !last)
        throw new AppError('Either `first` or `last` is required', 400)
    if (after && before)
        throw new AppError(
            '`after` and `before` cannot be used at the same time',
            400,
        )
    if (search && last)
        throw new AppError('`search` and `last` is not allowed', 400)

    if (search) {
        let score = null
        if (after) {
            const date = new Date(after)
            const result: any = await this.BooksModel.findOne(
                {
                    created: date,
                    $text: { $search: search },
                },
                { score: { $meta: 'textScore' } },
            )
            score = result._doc.score
        }

        const filter = { score: { $lt: score } }
        const limit = first ? first : last!

        const books = await this.BooksModel.aggregate([
            { $match: { $text: { $search: search } } },
            { $addFields: { score: { $meta: 'textScore' }, id: '$_id' } },
            ...(score ? [{ $match: filter }] : []),
            { $sort: { score: { $meta: 'textScore' } } },
            { $limit: limit },
        ])

        return books
    } else {
        const sort = { created: first ? -1 : 1 }
        const limit = first ? first : last!

        const books = await this.BooksModel.find({
            ...(after ? { created: { $lt: new Date(after) } } : null),
            ...(before ? { created: { $gt: new Date(before) } } : null),
        })
            .sort(sort)
            .limit(limit)
            .exec()

        return books
    }
}
```
\$\endgroup\$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.