Question

Exemple:

> db.stuff.save({"foo":"bar"});

> db.stuff.find({"foo":"bar"}).count();
1
> db.stuff.find({"foo":"BAR"}).count();
0
Était-ce utile?

La solution

Vous pouvez utiliser un regex.

Dans votre exemple qui serait:

db.stuff.find( { foo: /^bar$/i } );

Je dois dire, cependant, peut-être que vous pourriez juste downcase (ou upcase) la valeur de la manière plutôt que supporter le coût supplémentaire à chaque fois que vous le trouverez. Il est évident que cela ne marchera pas pour les noms des personnes et autres, mais peut-être des cas d'utilisation comme des balises.

Autres conseils

Mise à jour:

La réponse originale est maintenant obsolète. MongoDB prend désormais en charge la recherche de texte intégral avancé, avec de nombreuses fonctionnalités.

RÉPONSE ORIGINAL:

Il convient de noter que la recherche avec le cas de regex insensible / i signifie que MongoDB ne peut pas effectuer une recherche par index, des requêtes sur grands ensembles de données peuvent prendre beaucoup de temps.

Même avec de petits ensembles de données, il est pas très efficace. Vous prenez un cpu beaucoup plus touché que vos bons de requête, qui pourrait devenir un problème si vous essayez d'atteindre l'échelle.

Comme alternative, vous pouvez stocker une copie majuscule et la recherche contre cela. Par exemple, j'ai une table utilisateur qui a un nom d'utilisateur qui est mélangé cas, mais l'id est une copie majuscule du nom d'utilisateur. Cela garantit sensible à la casse duplication est impossible (à la fois « Foo » et « foo » ne sera pas autorisé), et je peux effectuer une recherche par id = username.toUpperCase () pour obtenir une recherche insensible à la casse pour le nom d'utilisateur.

Si votre champ est grand, comme un corps de message, la duplication des données est probablement pas une bonne option. Je crois en utilisant un indexeur étranger comme Apache Lucene est la meilleure option dans ce cas.

Gardez à l'esprit que l'exemple précédent:

db.stuff.find( { foo: /bar/i } );

provoquera toutes les entrées contenant bar pour correspondre à la requête (bar1, barxyz, openbar), il pourrait être très dangereux pour une recherche nom d'utilisateur sur une fonction auth ...

Vous devrez peut-être faire correspondre uniquement le terme de recherche en utilisant la syntaxe appropriée regexp comme:

db.stuff.find( { foo: /^bar$/i } );

Voir http://www.regular-expressions.info/ l'aide de la syntaxe des expressions régulières

Si vous avez besoin pour créer l'expression régulière d'une variable, cela est une bien meilleure façon de le faire: https: // stackoverflow. com / a / 10728069/309514

Vous pouvez faire quelque chose comme:

var string = "SomeStringToFind";
var regex = new RegExp(["^", string, "$"].join(""), "i");
// Creates a regex of: /^SomeStringToFind$/i
db.stuff.find( { foo: regex } );

Ceci a l'avantage être être plus programmatique ou vous pouvez obtenir un gain de performances en compilant à l'avance si vous réutilisez beaucoup.

A partir de MongoDB, la méthode recommandée pour effectuer des recherches insensibles à la casse rapide est d'utiliser un Index Insensible Case .

Personnellement, j'envoyé par courriel un des fondateurs de ce travail vous plaît obtenir, et il fait y arriver! Il était question de , et beaucoup ont demandé la fonction. Voici comment cela fonctionne:

Un indice insensible à la casse est réalisée en spécifiant une classement avec une force de 1 ou 2. Vous pouvez créer un index insensible à la casse comme ceci:

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

Vous pouvez également spécifier un classement par défaut par collection lors de leur création:

db.createCollection('cities', { collation: { locale: 'en', strength: 2 } } );

Dans les deux cas, afin d'utiliser l'index de la casse, vous devez spécifier le même classement dans l'opération de find qui a été utilisé lors de la création de l'indice ou la collection:

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

retournera "New York", "New York", "New York" etc.

Autres notes

  • Les réponses suggèrent d'utiliser recherche de texte intégral sont erronés dans ce cas (et potentiellement dangereux ). La question était de faire une requête insensible à la casse, par exemple username: 'bill' BILL correspondant ou Bill, pas une requête de recherche en texte intégral, qui correspondraient aussi découle des mots de bill, tels que Bills, billed etc.
  • Les réponses suggèrent d'utiliser des expressions régulières sont lentes, parce que même avec des index, le documentation indique :

      

    « requêtes d'expression régulière insensible à la casse ne peuvent généralement pas utiliser efficacement les index. La mise en œuvre de regex $ ne sont pas conscients collecte et ne peut pas utiliser les indices insensibles à la casse. »

    répond $regex courent également le risque d'injection d'entrée utilisateur .

db.zipcodes.find({city : "NEW YORK"}); // Case-sensitive
db.zipcodes.find({city : /NEW york/i}); // Note the 'i' flag for case-insensitivity

TL; DR

bonne façon de le faire dans mongo

Ne pas utiliser RegExp

Go naturel et utiliser l'indexation de MongoDB intégré, recherche

Étape 1:

db.articles.insert(
   [
     { _id: 1, subject: "coffee", author: "xyz", views: 50 },
     { _id: 2, subject: "Coffee Shopping", author: "efg", views: 5 },
     { _id: 3, subject: "Baking a cake", author: "abc", views: 90  },
     { _id: 4, subject: "baking", author: "xyz", views: 100 },
     { _id: 5, subject: "Café Con Leche", author: "abc", views: 200 },
     { _id: 6, subject: "Сырники", author: "jkl", views: 80 },
     { _id: 7, subject: "coffee and cream", author: "efg", views: 10 },
     { _id: 8, subject: "Cafe con Leche", author: "xyz", views: 10 }
   ]
)

Étape 2:

Nécessité de créer un index sur quel que soit TEXTE que vous souhaitez rechercher, sans requête d'indexation sera extrêmement lente

db.articles.createIndex( { subject: "text" } )

Étape 3:

db.articles.find( { $text: { $search: "coffee",$caseSensitive :true } } )  //FOR SENSITIVITY
db.articles.find( { $text: { $search: "coffee",$caseSensitive :false } } ) //FOR INSENSITIVITY
db.company_profile.find({ "companyName" : { "$regex" : "Nilesh" , "$options" : "i"}});

Mongo (version 2.0.0) ne permet pas de recherches sensibles à la casse contre les champs indexés - voir leur documentation . Pour les champs non indexés, les expressions rationnelles figurant dans les autres réponses devraient être bien.

La meilleure méthode est dans votre langue de choix, lors de la création d'une enveloppe de modèle pour vos objets, demandez à votre méthode save () itérer à travers un ensemble de champs que vous serez effectuant une recherche sur qui sont également indexés; les ensemble de champs devraient avoir minuscules homologues qui sont ensuite utilisés pour la recherche.

Chaque fois que l'objet est enregistré à nouveau, les propriétés minuscules sont ensuite vérifiées et mises à jour avec toutes les modifications apportées aux propriétés principales. Cela fera en sorte que vous pouvez effectuer une recherche efficace, mais cacher le travail supplémentaire nécessaire pour mettre à jour les champs chaque fois lc.

Les champs minuscules pourraient être une clé: magasin d'objets de valeur ou tout simplement le nom du champ avec un LC_ préfixé. J'utilise le second pour simplifier l'interrogation (l'interrogation d'objet profond peut être source de confusion parfois).

Remarque: vous voulez indexer les champs LC_, et non pas les principaux domaines qu'ils sont basés hors de.

Supposons que vous voulez rechercher « colonne » dans « Table » et que vous voulez cas la recherche insenstive. La meilleure et efficace est comme ci-dessous;

//create empty JSON Object
mycolumn = {};

//check if column has valid value
if(column) {
    mycolumn.column = {$regex: new RegExp(column), $options: "i"};
}
Table.find(mycolumn);

Au-dessus de code ajoute que la valeur de votre recherche comme RegEx et recherche avec des critères de insensitve fixés par « i » en option.

Bonne chance.

Une chose très importante à garder à l'esprit lorsque vous utilisez une requête basée Regex - Lorsque vous faites cela pour un système de connexion, échapper à chaque caractère que vous recherchez, et ne pas oublier les ^ et les opérateurs $. Lodash a une fonction bien pour cette , si vous utilisez déjà:

db.stuff.find({$regex: new RegExp(_.escapeRegExp(bar), $options: 'i'})

Pourquoi? Imaginez un utilisateur entrant .* comme son nom d'utilisateur. Cela correspondrait tous les noms d'utilisateur, ce qui permet une connexion simplement en deviner le mot de passe de tout utilisateur.

En utilisant Mongoose cela a fonctionné pour moi:

var find = function(username, next){
    User.find({'username': {$regex: new RegExp('^' + username, 'i')}}, function(err, res){
        if(err) throw err;
        next(null, res);
    });
}

Le cadre d'agrégation a été introduit dans MongoDB 2.2. Vous pouvez utiliser l'opérateur de chaîne « strcasecmp de $ » pour faire une comparaison insensible à la casse entre les chaînes. Il est plus recommandé et plus facile que d'utiliser regex.

Voici le document officiel de l'opérateur de commande d'agrégation: https://docs.mongodb.com/manual/reference/operator/aggregation/strcasecmp/#exp._S_strcasecmp .

Vous pouvez utiliser Indices de cas Insensible :

L'exemple suivant crée une collection sans classement par défaut, ajoute un index sur le champ de nom avec une collation cas insensible. International Components for 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 classement par défaut:

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

Pour rechercher une variable et échapper:

const escapeStringRegexp = require('escape-string-regexp')
const name = 'foo'
db.stuff.find({name: new RegExp('^' + escapeStringRegexp(name) + '$', 'i')})   

Échapper la variable protège la requête contre les attaques avec «* » ou d'autres expressions régulières.

échapper-string-regexp

J'ai créé simple Func pour le cas regex insensible, que je l'utilise dans mon filtre.

private Func<string, BsonRegularExpression> CaseInsensitiveCompare = (field) => 
            BsonRegularExpression.Create(new Regex(field, RegexOptions.IgnoreCase));

Ensuite, vous filtrez simplement sur un champ comme suit.

db.stuff.find({"foo": CaseInsensitiveCompare("bar")}).count();

L'utilisation d'un filtre fonctionne pour moi en C #.

string s = "searchTerm";
    var filter = Builders<Model>.Filter.Where(p => p.Title.ToLower().Contains(s.ToLower()));
                var listSorted = collection.Find(filter).ToList();
                var list = collection.Find(filter).ToList();

Il peut même utiliser l'index parce que je crois que les méthodes sont appelées après le retour se passe mais je n'ai pas testé ceci encore.

Cela évite aussi un problème de

var filter = Builders<Model>.Filter.Eq(p => p.Title.ToLower(), s.ToLower());

que MongoDB penseront p.Title.ToLower () est une propriété et ne sera pas la carte correctement.

Comme vous pouvez le voir dans mongo docs - depuis la version 3.2 de l'indice $text est insensible à la casse par défaut: https://docs.mongodb.com/manual/core/index-text/#text-index-case-insensitivity

Créer un index de texte et < a href = "https://docs.mongodb.com/manual/reference/operator/query/text/#op._S_text" rel = "nofollow noreferrer"> utiliser l'opérateur de texte $ dans votre requête.

Ils ont été testés pour la recherche de chaîne

{'_id': /.*CM.*/}               ||find _id where _id contains   ->CM
{'_id': /^CM/}                  ||find _id where _id starts     ->CM
{'_id': /CM$/}                  ||find _id where _id ends       ->CM

{'_id': /.*UcM075237.*/i}       ||find _id where _id contains   ->UcM075237, ignore upper/lower case
{'_id': /^UcM075237/i}          ||find _id where _id starts     ->UcM075237, ignore upper/lower case
{'_id': /UcM075237$/i}          ||find _id where _id ends       ->UcM075237, ignore upper/lower case

Je l'avais fait face à un problème similaire et c'est ce qui a fonctionné pour moi:

  const flavorExists = await Flavors.findOne({
    'flavor.name': { $regex: flavorName, $options: 'i' },
  });
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top