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

Any way to make the filter/or conditions case insensitive? #77

Closed
chriszrc opened this issue May 10, 2019 · 12 comments
Closed

Any way to make the filter/or conditions case insensitive? #77

chriszrc opened this issue May 10, 2019 · 12 comments

Comments

@chriszrc
Copy link

Seems like a common requirement, if it's not present already, do you think it would be hard to add?

@fwoelffel
Copy link
Member

Doesn't this have something to do with you database collation? I believe SQL queries are case sensitive by default.

@chriszrc
Copy link
Author

Right, sql queries are case sensitive by default, that's why I want a case insensitive way to do the filtering, so the api can respond to a request for "column=a" and "column=A" and do a query like "lower(column) = lower(:paramA)" automatically

@hakimio
Copy link

hakimio commented May 23, 2019

All the "LIKE" conditions should be case insensitive: starts, ends, cont, excl.

@fwoelffel
Copy link
Member

fwoelffel commented May 23, 2019

All the "LIKE" conditions should be case insensitive: starts, ends,cont, excl.

This should be an option and not the default behavior. Otherwise it could break a lot of applications.

EDIT: I think this is what you meant, but I thought this ought to be clearly stated 😉

@hakimio
Copy link

hakimio commented May 23, 2019

This should be an option and not the default behavior. Otherwise it could break a lot of applications.

Actually this seems to be different from one database to another. For example, MySQL LIKE is case-insensitive and in PostgreSQL it's case sensitive. And you use different methods depending on DB to change this behavior.

@fwoelffel
Copy link
Member

You're almost right. From what I know that mainly depends on your collation, but I might be wrong. Sometimes, the collation has been chosen by the devs to have case sensitive searches, sometimes it's the opposite. Thus, @nestjsx/crud should never enforce such behavior by default.

Anyway, let's stick to the original subject.
@zMotivat0r would having a caseSentitive: boolean property in the FilterOptions be an acceptable option?

@michaelyali
Copy link
Member

@fwoelffel yep, I think we can provide some option and adjust query interceptor.

@jayakusumah
Copy link

jayakusumah commented Aug 3, 2019

Will the feature be available? sometimes we need query like this.

where("LOWER(post.title) = LOWER(:title)", {title}) (for PostgreSQL)

@jakubszalaty
Copy link

jakubszalaty commented Sep 27, 2019

Workaround (for PostgresSQL)
In app.module.ts add:

// @ts-ignore
TypeOrmCrudService.prototype.mapOperatorsToQuery = function(cond: QueryFilter, param: any): { str: string; params: ObjectLiteral } {
    const field = this.getFieldWithAlias(cond.field)
    let str: string
    let params: ObjectLiteral

    switch (cond.operator) {
        case 'eq':
            str = `${field} = :${param}`
            break

        case 'ne':
            str = `${field} != :${param}`
            break

        case 'gt':
            str = `${field} > :${param}`
            break

        case 'lt':
            str = `${field} < :${param}`
            break

        case 'gte':
            str = `${field} >= :${param}`
            break

        case 'lte':
            str = `${field} <= :${param}`
            break

        case 'starts':
            str = `${field} ILIKE :${param}`
            params = { [param]: `${cond.value}%` }
            break

        case 'ends':
            str = `${field} ILIKE :${param}`
            params = { [param]: `%${cond.value}` }
            break

        case 'cont':
            str = `${field} ILIKE :${param}`
            params = { [param]: `%${cond.value}%` }
            break

        case 'excl':
            str = `${field} NOT ILIKE :${param}`
            params = { [param]: `%${cond.value}%` }
            break

        case 'in':
            /* istanbul ignore if */
            if (!Array.isArray(cond.value) || !cond.value.length) {
                this.throwBadRequestException(`Invalid column '${cond.field}' value`)
            }
            str = `${field} IN (:...${param})`
            break

        case 'notin':
            /* istanbul ignore if */
            if (!Array.isArray(cond.value) || !cond.value.length) {
                this.throwBadRequestException(`Invalid column '${cond.field}' value`)
            }
            str = `${field} NOT IN (:...${param})`
            break

        case 'isnull':
            str = `${field} IS NULL`
            params = {}
            break

        case 'notnull':
            str = `${field} IS NOT NULL`
            params = {}
            break

        case 'between':
            /* istanbul ignore if */
            if (!Array.isArray(cond.value) || !cond.value.length || cond.value.length !== 2) {
                this.throwBadRequestException(`Invalid column '${cond.field}' value`)
            }
            str = `${field} BETWEEN :${param}0 AND :${param}1`
            params = {
                [`${param}0`]: cond.value[0],
                [`${param}1`]: cond.value[1],
            }
            break

        /* istanbul ignore next */
        default:
            str = `${field} = :${param}`
            break
    }

    if (typeof params === 'undefined') {
        params = { [param]: cond.value }
    }

    return { str, params }
}

It's based on https://github.com/nestjsx/crud/blob/master/packages/crud-typeorm/src/typeorm-crud.service.ts#L615

@sandeshgb
Copy link

@jakubszalaty really appretiate your workaround, but still I'm expecting a much better solution.
@fwoelffel @zMotivat0r as you have suggested any property to achieve to same?

yharaskrik pushed a commit to yharaskrik/crud that referenced this issue Dec 24, 2019
@ElegantSoft
Copy link

now you can use

$contL

@Aashir1
Copy link

Aashir1 commented Apr 17, 2024

Workaround (for PostgresSQL) In app.module.ts add:

// @ts-ignore
TypeOrmCrudService.prototype.mapOperatorsToQuery = function(cond: QueryFilter, param: any): { str: string; params: ObjectLiteral } {
    const field = this.getFieldWithAlias(cond.field)
    let str: string
    let params: ObjectLiteral

    switch (cond.operator) {
        case 'eq':
            str = `${field} = :${param}`
            break

        case 'ne':
            str = `${field} != :${param}`
            break

        case 'gt':
            str = `${field} > :${param}`
            break

        case 'lt':
            str = `${field} < :${param}`
            break

        case 'gte':
            str = `${field} >= :${param}`
            break

        case 'lte':
            str = `${field} <= :${param}`
            break

        case 'starts':
            str = `${field} ILIKE :${param}`
            params = { [param]: `${cond.value}%` }
            break

        case 'ends':
            str = `${field} ILIKE :${param}`
            params = { [param]: `%${cond.value}` }
            break

        case 'cont':
            str = `${field} ILIKE :${param}`
            params = { [param]: `%${cond.value}%` }
            break

        case 'excl':
            str = `${field} NOT ILIKE :${param}`
            params = { [param]: `%${cond.value}%` }
            break

        case 'in':
            /* istanbul ignore if */
            if (!Array.isArray(cond.value) || !cond.value.length) {
                this.throwBadRequestException(`Invalid column '${cond.field}' value`)
            }
            str = `${field} IN (:...${param})`
            break

        case 'notin':
            /* istanbul ignore if */
            if (!Array.isArray(cond.value) || !cond.value.length) {
                this.throwBadRequestException(`Invalid column '${cond.field}' value`)
            }
            str = `${field} NOT IN (:...${param})`
            break

        case 'isnull':
            str = `${field} IS NULL`
            params = {}
            break

        case 'notnull':
            str = `${field} IS NOT NULL`
            params = {}
            break

        case 'between':
            /* istanbul ignore if */
            if (!Array.isArray(cond.value) || !cond.value.length || cond.value.length !== 2) {
                this.throwBadRequestException(`Invalid column '${cond.field}' value`)
            }
            str = `${field} BETWEEN :${param}0 AND :${param}1`
            params = {
                [`${param}0`]: cond.value[0],
                [`${param}1`]: cond.value[1],
            }
            break

        /* istanbul ignore next */
        default:
            str = `${field} = :${param}`
            break
    }

    if (typeof params === 'undefined') {
        params = { [param]: cond.value }
    }

    return { str, params }
}

It's based on https://github.com/nestjsx/crud/blob/master/packages/crud-typeorm/src/typeorm-crud.service.ts#L615

Is the community still relying on this workaround, or has a proper fix been found for comparing strings case insensitively?

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

9 participants