web-dev-qa-db-fra.com

MongoDB et C #: recherche insensible à la casse

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)));
33
Andrew Orsich

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.

56
i3arnon

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.

35
Matt Canty

essayez d'utiliser quelque chose comme ceci:

Query.Matches("FieldName", BsonRegularExpression.Create(new Regex(searchKey, RegexOptions.IgnoreCase)))
14

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

12
Thilo

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());
4
Thomas Teilmann

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

1
Kostassoid

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();
1
A_Arnold

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

  1. Utilisation du même classement lors de recherches sur la collection MongoDb.

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;
}
0
iberodev

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()))));
0
user2078169