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)));
30
demandé sur i3arnon 2010-12-16 11:56:31

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.

52
répondu i3arnon 2014-11-22 11:19:48

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.

33
répondu Matt Canty 2017-08-25 14:57:39

essayez d'utiliser quelque chose comme ceci:

Query.Matches("FieldName", BsonRegularExpression.Create(new Regex(searchKey, RegexOptions.IgnoreCase)))
14
répondu Andrei Andrushkevich 2010-12-16 09:05:13

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).

12
répondu Thilo 2010-12-16 09:03:46

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());
4
répondu Thomas Teilmann 2016-05-20 13:35:58

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.

1
répondu Kostassoid 2011-07-26 14:47:50

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();
1
répondu A_Arnold 2017-08-07 22:41:34

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()))));
0
répondu user2078169 2013-02-16 11:14:46

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

  1. 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;
}
0
répondu iberodev 2018-06-09 22:49:33