MongoDB et C#: recherche insensible à la casse
j'utilise MongoDB et C# pilote pour MongoDB.
j'ai récemment découvert que toutes les requêtes en MongoDB sont sensibles à la casse. Comment puis-je effectuer une recherche non sensible à la casse?
j'ai trouvé une manière de faire ceci:
Query.Matches(
"FirstName",
BsonRegularExpression.Create(new Regex(searchKey,RegexOptions.IgnoreCase)));
9 réponses
la façon la plus simple et la plus sûre de le faire est d'utiliser Linq
:
var names = namesCollection.AsQueryable().Where(name =>
name.FirstName.ToLower().Contains("hamster"));
Comme expliqué dans le tutorielToLower
,ToLowerInvariant
,ToUpper
et ToUpperInvariant
tous effectuent les matches d'une manière insensible à la casse. Après cela, vous pouvez utiliser toutes les méthodes de chaîne supportées comme Contains
ou StartsWith
.
cet exemple générera:
{
"FirstName" : /hamster/is
}
i
l'option le rend insensible à la casse.
je viens d'implémenter ceci beaucoup plus simple que toutes les autres suggestions. Cependant je me rends compte en raison de l'âge de cette question, cette fonctionnalité peut ne pas avoir été disponible à l'époque.
Utilisez les options du constructeur BSON Regular Expression pour passer en cas d'insensibilité. J'ai juste regardé le code source et j'ai trouvé que " je " est tout ce dont tu as besoin. Exemple.
var regexFilter = Regex.Escape(filter);
var bsonRegex = new BsonRegularExpression(regexFilter, "i");
Query.Matches("MyField", bsonRegex);
Vous ne devriez pas avoir à tenir des registres deux fois pour la recherche.
essayez d'utiliser quelque chose comme ceci:
Query.Matches("FieldName", BsonRegularExpression.Create(new Regex(searchKey, RegexOptions.IgnoreCase)))
vous aurez probablement à stocker le champ deux fois, une fois avec sa valeur réelle, et encore dans toutes les minuscules. Vous pouvez alors interroger la version lowercased pour une recherche non sensible à la casse (n'oubliez pas de mettre aussi lowercase la chaîne de requête).
cette approche fonctionne (ou est nécessaire) pour de nombreux systèmes de bases de données, et elle devrait donner de meilleurs résultats que les techniques basées sur l'expression régulière (au moins pour le préfixe ou la correspondance exacte).
Comme i3arnon répondu, vous pouvez utiliser Queryable de faire une comparaison de la casse/recherche. Ce que j'ai découvert, c'est que je ne pouvais pas utiliser string.Méthode Equals (), car il n'est pas pris en charge. Si vous avez besoin de faire une comparaison, Contains() ne sera malheureusement pas adapté ce qui m'a fait lutter pour une solution, pendant un certain temps.
pour ceux qui veulent faire une comparaison de chaînes, utilisez simplement == au lieu de .Égal.)(
Code:
var names = namesCollection.AsQueryable().Where(name =>
name.FirstName.ToLower() == name.ToLower());
Dans le cas où quelqu'un d'autre, vous demandez-vous, à l'aide de courant-mongo add-on, vous pouvez utiliser Linq pour la requête comme ça:
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, Chaîne.Equals() n'est pas encore prise en charge.
Vous pouvez également utiliser les filtres intégrés de MongoDB. Il peut être plus facile d'utiliser certaines des 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();
Une façon de le faire est d'utiliser MongoDB.Bfils.Classe BsonJavaScript comme montré ci-dessous
store.FindAs<Property>(Query.Where(BsonJavaScript.Create(string.Format("this.City.toLowerCase().indexOf('{0}') >= 0", filter.City.ToLower()))));
Pour MongoDB 3.4+ la méthode recommandée est d'utiliser des index. Voir https://jira.mongodb.org/browse/DOCS-11105?focusedCommentId=1859745&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-1859745
je cherche avec succès avec la case insensible par: 1. Création d'un index avec Collation pour une locale (E. g: "en") et avec une force de 1 ou 2. Voir https://docs.mongodb.com/manual/core/index-case-insensitive/ pour d'autres détails
- en utilisant la même Collation lors des recherches sur la collection MongoDb.
comme exemple:
créer une collation avec la Force 1 ou 2 pour insensible à la casse
private readonly Collation _caseInsensitiveCollation = new Collation("en", strength: CollationStrength.Primary);
créer un index. Dans mon cas, je l'indice de 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 la recherche, assurez-vous d'utiliser la même Collation:
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;
}