Node.js e la compatibilità tra i tipi di dati JavaScript e quelli di MongoDB

Short link

JavaScript è un linguaggio che dispone di pochi tipi di dati. Questa caratteristica può risultare problematica quando si ha a che fare con un database come MongoDB.

Gli operatori di confronto sui dati di MongoDB sono concepiti per effettuare una verifica sul tipo di dati passato alla query. Se il tipo di dati non corrisponde con quello del campo scelto, il confronto non avrà luogo.

Consideriamo questa query:


db.products.find({price: {$gte: 100}});

Questa query funzionerà nel modo sperato solo se il campo price contiene valori interi. Se al contrario dovesse contenere anche valori in virgola mobile, l'operatore verrebbe semplicemente ignorato.

Se stiamo implementando un sistema di ricerca basato sul prezzo, potremmo scrivere il seguente codice:


app.get('/search', (req, res) => {
    let price = req.query.price;
    // TODO: validazione
    if(price.length > 0) {
        db.products.find({price: {$gte: price}}).then(results => {
            res.json(results);
        }).catch(err => {
            res.json(err);
        });
    } else {
       res.json({});
    }
});

Cosa succede quando riceviamo dal form di ricerca un valore intero? Potremmo provare a convertirlo in un valore in virgola mobile:


let value = '100';

let v = parseFloat(value); // '100'
let k = parseFloat(Number(value).toFixed(2)); '100'

Questo accade perché JavaScript non ha un tipo di dati per i valori in virgola mobile e per gli interi come MongoDB: entrambi sono istanze di Number. Dobbiamo quindi ricorrere ad una diversa soluzione:


const convertIntToDouble = (value) => {
  if( /^\d+$/.test( value ) ) {
      let n = parseInt(value, 10);
      return (n + 0.01);
  } else {
      return -1;
  }
}

In pratica aggiungiamo manualmente una parte decimale trascurabile al numero intero in modo da avere come risultato un numero in virgola mobile.