Search code examples
mongodbtypeorm

How to set collation rules with TypeORM for MongoDB?


I am using mongoDB with TypeORM to create queries, like this:

      const repository = queryRunner.manager.getRepository("...");

      const conditions = { take: ..., skip: ..., where: {...}, order: ... };

      const [entities, count] = await repository.findAndCount(conditions);


      return {
        data: entities as T[],
        count: count
      };

This works without any issue. My current task is to implement localized collation behaviour. Currently, by default, special characters are not ordered by hungarian rules (A->Á->B->C etc.) and there is an upper-lower character order which I do not want to have (a->A->b->B order).

How can I do that? Here is what I have tried so far:

  1. tried setting ColumnOptions in entities:

In my base entities, setting {name: ..., collation: 'hu', charset: 'utf-8'} did not have any effect.

  1. Tried setting collation as a FindCondition:
      const repository = queryRunner.manager.getRepository("...");

      const conditions = { take: ..., skip: ..., where: {...}, order: ... };

      conditions['collation'] = {
        locale: 'hu',
        caseLevel: false,
        caseFirst: false,
      }

      const [entities, count] = await repository.findAndCount(conditions);


      return {
        data: entities as T[],
        count: count
      };

But this has no effect on the query result whatsoever. At this point I am confused, as far as I could tell, both approach should work :\


Solution

  • As far as my research went, it seems not possible after the database is initialized :(

    I should have created different collation options while defining the collection.

    I can add indexes, however. If my queries specify the same collation options, these might work.

    Edit: this works :)

    I must create an index (or indexes if I wish to use multiple) ONCE. For example, in the mongoDB console:

    db.<tablenamw>.createIndex({hungarianName: 1}, {name: 'hungarianname_hu', collation: {locale:"hu", strength: 2}})
    

    Sadly, TypeORM does not support calling collation options directly, in find, findandcount etc. methods, so we must fall back to use NodeJS MongoDB queries:

    const query = await mongoDbQueryRunnerCollection
                .find(..., {collation: ({locale: "hu", strength: 1})})
                .sort(...)
                .skip(...)
                .limit(...
    

    where mongoDbQueryRunnerCollection is a direct collection reference object in mongodb nodejs api.