J'utilise MongoDB et le pilote C # pour MongoDB .
J'ai récemment découvert que toutes les requêtes dans MongoDB sont sensibles à la casse. Comment puis-je effectuer une recherche insensible à la casse?
J'ai trouvé un moyen de faire ça:
Query.Matches(
"FirstName",
BsonRegularExpression.Create(new Regex(searchKey,RegexOptions.IgnoreCase)));
Le moyen le plus simple et le plus sûr consiste à utiliser Linq
:
var names = namesCollection.AsQueryable().Where(name =>
name.FirstName.ToLower().Contains("hamster"));
Comme expliqué dans le tutorielToLower
, ToLowerInvariant
, ToUpper
et ToUpperInvariant
, tous effectuent des correspondances sans tenir compte de la casse. Après cela, vous pouvez utiliser toutes les méthodes de chaîne prises en charge, telles que Contains
ou StartsWith
.
Cet exemple va générer:
{
"FirstName" : /hamster/is
}
L'option i
le rend insensible à la casse.
Je viens de mettre en œuvre cette beaucoup plus simple que l'une des autres suggestions. Cependant, je me rends compte qu'en raison de l'âge de cette question, cette fonctionnalité n'était peut-être pas disponible à l'époque.
Utilisez les options du constructeur Bson Regular Expression pour passer en cas d'insensibilité à la casse. Je viens de jeter un coup d'œil au code source et de constater que «je» est tout ce dont vous avez besoin. Par exemple.
var regexFilter = Regex.Escape(filter);
var bsonRegex = new BsonRegularExpression(regexFilter, "i");
Query.Matches("MyField", bsonRegex);
Vous ne devriez pas avoir à garder deux fois les enregistrements pour la recherche.
essayez d'utiliser quelque chose comme ceci:
Query.Matches("FieldName", BsonRegularExpression.Create(new Regex(searchKey, RegexOptions.IgnoreCase)))
Vous devrez probablement stocker le champ deux fois, une fois avec sa valeur réelle, et encore une fois en minuscule. Vous pouvez ensuite interroger la version minuscule pour une recherche ne respectant pas la casse (n'oubliez pas de mettre également la chaîne de requête en minuscule).
Cette approche fonctionne (ou est nécessaire) pour de nombreux systèmes de base de données et devrait fonctionner mieux que les techniques basées sur des expressions régulières (au moins pour le préfixe ou la correspondance exacte).
Comme l'a répondu i3arnon, vous pouvez utiliser Queryable pour effectuer une comparaison/recherche insensible à la casse. Ce que j’ai découvert, c’est que je ne pouvais pas utiliser la méthode string.Equals (), car elle n’est pas prise en charge. Si vous avez besoin de faire une comparaison, Contains () ne conviendra malheureusement pas, ce qui m’a empêché de chercher une solution pendant un bon bout de temps.
Pour ceux qui souhaitent faire une comparaison de chaînes, utilisez simplement == au lieu de .Equals ().
Code:
var names = namesCollection.AsQueryable().Where(name =>
name.FirstName.ToLower() == name.ToLower());
Au cas où quelqu'un d'autre se demanderait, en utilisant fluent-mongo add-on, vous pouvez utiliser Linq pour interroger de la sorte:
public User FindByEmail(Email email)
{
return session.GetCollection<User>().AsQueryable()
.Where(u => u.EmailAddress.ToLower() == email.Address.ToLower()).FirstOrDefault();
}
Ce qui aboutit à une requête JS correcte. Malheureusement, String.Equals () n'est pas encore supporté.
Vous pouvez également utiliser les filtres intégrés de MongoDB. Cela peut faciliter l'utilisation de certaines méthodes de Mongo.
var filter = Builders<Model>.Filter.Where(p => p.PropertyName.ToLower().Contains(s.ToLower()));
var list = collection.Find(filter).Sort(mySort).ToList();
Pour MongoDB 3.4+, la méthode recommandée consiste à utiliser des index ..__ Voir https://jira.mongodb.org/browse/DOCS-11105?focusedCommentId=1859745&page=com.atlassian.jira.plugin.system.ystuetabpanels: comment-tabpanel # comment-1859745
Je cherche avec succès avec insensible à la casse par: 1. Création d'un index avec Collation pour une locale (par exemple: "en") et avec une force de 1 ou 2. Voir https://docs.mongodb.com/manual/core/index-case-insensitive/ pour plus de détails
Par exemple:
Créez une collation de force 1 ou 2 pour les majuscules et les minuscules
private readonly Collation _caseInsensitiveCollation = new Collation("en", strength: CollationStrength.Primary);
Créez un index. Dans mon cas j'indexe plusieurs champs:
private void CreateIndex()
{
var indexOptions = new CreateIndexOptions {Collation = _caseInsensitiveCollation};
var indexDefinition
= Builders<MyDto>.IndexKeys.Combine(
Builders<MyDto>.IndexKeys.Ascending(x => x.Foo),
Builders<MyDto>.IndexKeys.Ascending(x => x.Bar));
_myCollection.Indexes.CreateOne(indexDefinition, indexOptions);
}
Lors de l'interrogation, assurez-vous d'utiliser le même classement:
public IEnumerable<MyDto> GetItems()
{
var anyFilter = GetQueryFilter();
var anySort = sortBuilder.Descending(x => x.StartsOn);
var findOptions = new FindOptions {Collation = _caseInsensitiveCollation};
var result = _salesFeeRules
.Find(anyFilter, findOptions)
.Sort(anySort)
.ToList();
return result;
}
Une façon de le faire est d'utiliser la classe MongoDB.Bson.BsonJavaScript comme indiqué ci-dessous
store.FindAs<Property>(Query.Where(BsonJavaScript.Create(string.Format("this.City.toLowerCase().indexOf('{0}') >= 0", filter.City.ToLower()))));