Turkish characters and mongoose

Viewed 278

I am trying to search in a collection by a word. So I have record like this:

{ 
    "_id" : ObjectId("5ec2e9d0543e75377e9f3981"), 
    "text" : "işlemci", 
    "question" : ObjectId("5ec2c3f36700e13311592917"), 
    "createdAt" : ISODate("2020-05-18T20:02:24.641+0000"), 
    "updatedAt" : ISODate("2020-05-18T20:02:24.641+0000"), 
    "__v" : NumberInt(0)
}

And i am using following query to find that entry:

var answer = "islemci"
    const answerRegex = new RegExp(answer, 'i');

    const answers = await Answer
        .find({
            text: answerRegex,
            question: questionId
        })
        .populate('question', 'text -_id')
        .select('text question');

It doesn't find any records, because we passed "islemci" value to our answer variable. If i try with "işlemci" it finds the entry.

How can i ignore the Turkish characters when i am searching?

Turkish characters: https://en.wikipedia.org/wiki/Wikipedia:Turkish_characters

1 Answers

Language-specific rules for strings comparison can be handled using collation. Basically in your case you can use en_US for locale and specify strength 1 which will ignore any non-english characters.

1 Primary level of comparison. Collation performs comparisons of the base characters only, ignoring other differences such as diacritics and case.

In mongoose collation can be specified on the schema level:

const yourSchema = new Schema(
    {
        text: String,
        question: Schema.Types.ObjectId,
        createdAt: Date,
        updatedAt: Date,
    },
    { collation: { locale: 'en_US', strength: 1 } }
);

Whenever you call .find like this:

let doc = await Model.find({ text: 'islemci' });

mongoose will run following query:

db.col.find({ text: 'islemci' }, { collation: { locale: 'tr', strength: 1 }, projection: {} })

It works for equality comparisons but unfortunately is not applicable for $regex:

The $regex implementation is not collation-aware

Related