web-dev-qa-db-fra.com

Comment faire des requêtes sans distinction de casse sur Mongodb?

var thename = 'Andrew';
db.collection.find({'name':thename});

Comment interroger la casse? Je veux trouver le résultat même si "Andrew";

72
user847495

La solution de Chris Fulstow fonctionnera (+1). Cependant, elle risque de ne pas être efficace, en particulier si votre collection est très volumineuse. Expressions régulières non enracinées (celles ne commençant pas par ^, qui ancre l'expression régulière au début de la chaîne), et ceux qui utilisent l'indicateur i pour l'insensibilité à la casse n'utiliseront pas les index, même s'ils existent.

Une autre option que vous pourriez envisager consiste à dénormaliser vos données pour stocker une version minuscule du champ name, par exemple sous la forme name_lower. Vous pouvez ensuite interroger efficacement cette information (surtout si elle est indexée) pour des correspondances exactes, insensibles à la casse, telles que:

db.collection.find({"name_lower": thename.toLowerCase()})

Ou avec un préfixe correspondant (une expression régulière enracinée) comme:

db.collection.find( {"name_lower":
    { $regex: new RegExp("^" + thename.toLowerCase(), "i") } }
);

Ces deux requêtes utiliseront un index sur name_lower.

103
dcrosta

Vous devez utiliser une casse expression régulière pour celle-ci, par exemple.

db.collection.find( { "name" : { $regex : /Andrew/i } } );

Pour utiliser le motif regex de votre variable thename, construisez un nouvel objet RegExp :

var thename = "Andrew";
db.collection.find( { "name" : { $regex : new RegExp(thename, "i") } } );

Mise à jour: Pour une correspondance exacte, vous devez utiliser l'expression régulière "name": /^Andrew$/i. Merci à Yannick L.

67
Chris Fulstow

Je l'ai résolu comme ça.

 var thename = 'Andrew';
 db.collection.find({'name': {'$regex': thename,$options:'i'}});

Si vous souhaitez interroger sur la 'correspondance exacte insensible à la casse', vous pouvez procéder comme suit.

var thename =  '^Andrew$';
db.collection.find({'name': {'$regex': thename,$options:'i'}});
27
RIPAN

MongoDB 3.4 inclut désormais la possibilité de créer un véritable index ne respectant pas la casse, ce qui augmentera considérablement la vitesse des recherches insensibles à la casse sur de grands ensembles de données. Il est fait en spécifiant une collation avec une force de 2.

La manière la plus simple de le faire est probablement de définir un classement sur la base de données. Ensuite, toutes les requêtes héritent de ce classement et l'utilisent:

db.createCollection("cities", { collation: { locale: 'en_US', strength: 2 } } )
db.names.createIndex( { city: 1 } ) // inherits the default collation

Vous pouvez aussi le faire comme ça:

db.myCollection.createIndex({city: 1}, {collation: {locale: "en", strength: 2}});

Et utilisez-le comme ceci:

db.myCollection.find({city: "new york"}).collation({locale: "en", strength: 2});

Cela retournera les villes nommées "new york", "New York", "New York", etc.

Pour plus d'informations: https://jira.mongodb.org/browse/SERVER-9

6
user3413723

Je viens de résoudre ce problème il y a quelques heures.

var thename = 'Andrew'
db.collection.find({ $text: { $search: thename } });
  • La sensibilité à la casse et la sensibilité diacritique sont définies sur false par défaut lorsque vous exécutez des requêtes de cette manière.

Vous pouvez même développer ceci en sélectionnant les champs de l'objet utilisateur d'Andrew dont vous avez besoin en procédant ainsi:

db.collection.find({ $text: { $search: thename } }).select('age height weight');

Référence: https://docs.mongodb.org/manual/reference/operator/query/text/#text

5
Briant Anthony
  1. Avec Mongoose (et Node), cela fonctionnait:

    • User.find({ email: /^[email protected]$/i })

    • User.find({ email: new RegExp( `^ $ {EmailVariable} $`, 'i')})

  2. Dans MongoDB, cela a fonctionné:

Les deux lignes sont insensibles à la casse. Le courrier électronique dans la base de données pourrait être [email protected] Et les deux lignes trouveront toujours l'objet dans la base de données.

De même, nous pourrions utiliser /^[email protected]$/i Et trouver toujours le courrier électronique: [email protected] Dans la base de données.

4
Raymond Gan

Pour trouver une chaîne insensible à la casse, utilisez ceci,

var thename = "Andrew";
db.collection.find({"name":/^thename$/i})
2
Pranit

Pour rechercher une chaîne littérale insensible à la casse:

Utiliser regex (recommandé)

db.collection.find({
    name: {
        $regex: new RegExp('^' + name.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '$', 'i')
    }
});

Utilisation d'un index minuscule (plus rapide)

db.collection.find({
    name_lower: name.toLowerCase()
});

Les expressions régulières sont plus lentes que les correspondances de chaînes littérales. Toutefois, un champ minuscule supplémentaire augmentera la complexité de votre code. En cas de doute, utilisez des expressions régulières. Je suggérerais de n'utiliser qu'un champ explicitement en minuscule s'il peut remplacer votre champ, c'est-à-dire que vous ne vous souciez pas de la casse en premier lieu.

Notez que vous devrez échapper le nom avant regex. Si vous voulez des caractères génériques saisis par l'utilisateur, préférez ajouter .replace(/%/g, '.*') après une évasion pour pouvoir faire correspondre "a%" à la recherche de tous les noms commençant par 'a'.

2
Yeti

La requête suivante trouvera les documents avec la chaîne requise () de manière insensible et avec une occurrence globale également

db.collection.find({name:{
                             $regex: new RegExp(thename, "ig")
                         }
                    },function(err, doc) {
                                         //Your code here...
                  });
1
prodeveloper

Vous pouvez utiliser les index non sensibles à la casse :

L'exemple suivant crée une collection sans classement par défaut, puis ajoute un index sur le champ de nom avec un classement ne respectant pas la casse. Composants internationaux pour Unicode

/*
* strength: CollationStrength.Secondary
* Secondary level of comparison. Collation performs comparisons up to secondary * differences, such as diacritics. That is, collation performs comparisons of 
* base characters (primary differences) and diacritics (secondary differences). * Differences between base characters takes precedence over secondary 
* differences.
*/
db.users.createIndex( { name: 1 }, collation: { locale: 'tr', strength: 2 } } )

Pour utiliser l'index, les requêtes doivent spécifier le même classement.

db.users.insert( [ { name: "Oğuz" },
                            { name: "oğuz" },
                            { name: "OĞUZ" } ] )

// does not use index, finds one result
db.users.find( { name: "oğuz" } )

// uses the index, finds three results
db.users.find( { name: "oğuz" } ).collation( { locale: 'tr', strength: 2 } )

// does not use the index, finds three results (different strength)
db.users.find( { name: "oğuz" } ).collation( { locale: 'tr', strength: 1 } )

ou vous pouvez créer une collection avec un classement par défaut:

db.createCollection("users", { collation: { locale: 'tr', strength: 2 } } )
db.users.createIndex( { name : 1 } ) // inherits the default collation
1
Gencebay D.