Search code examples
mongodbmongoosefind

Mongoose : find a field by expression


Here is my adresse Schema :

const adresseSchema = mongoose.Schema({
  adresseComplete: {
    type: String,
    required: true,
    trim: true,
  },
  ville: {
    type: String,
    required: false,
  },
  departement: {
    type: String,
    required: false,
  },
  region: {
    type: String,
    required: true,
  },
  pays: {
    type: String,
    required: true,
  },
});

And an example of document :

"adresse": {
    "_id": "642156ad876e0c4328e193e7",
    "ville": "Paris",
    "departement": "Département de Paris",
    "region": "Île-de-France",
    "pays": "France",
  },

The Application front-end sends to the back-end a "region" slugified like "ile-de-france"

Here is an example of the function which slugify the region label :

const slugify = (str) => {
  const map = {
    '-': ' |_',
    a: 'á|à|ã|â|ä|À|Á|Ã|Â|Ä',
    e: 'é|è|ê|ë|É|È|Ê|Ë',
    i: 'í|ì|î|ï|Í|Ì|Î|Ï',
    o: 'ó|ò|ô|õ|ö|Ó|Ò|Ô|Õ|Ö',
    u: 'ú|ù|û|ü|Ú|Ù|Û|Ü',
    c: 'ç|Ç',
    n: 'ñ|Ñ',
  };

  for (const pattern in map) str = str.replace(new RegExp(map[pattern], 'g'), pattern);

  return str.replace(/[^a-z\-0-9\s]/gi, '').toLowerCase();
};

How could I find in MongoDB all the adresses that macthes the slugified region ?

I saw that $where could do the job but I can't use this function on MongoDB SAAS Cluster ?


Solution

  • Looks like you need to use MongoDB Collation feature. For your specific case, you can create a case-insensitive index on the region field using collation and then perform a search using the same collation.

    First, you create an index with collation for the french locale.

    db.adresse.createIndex(
      { region: 1 },
      {
        collation: {
          locale: "fr", // French locale
          strength: 1, // Case-insensitive and accent-insensitive
        },
      }
    );
    

    Now, you can find all the addresses that match the slugified region using the same collation:

    db.adresse.find(
      { region: "ile-de-france" },
      {
        collation: {
          locale: "fr",
          strength: 1,
        },
      }
    );