Estoy usando MongoDB y la C# driver de MongoDB.

Recientemente he descubierto que todas las consultas en MongoDB son sensibles a las mayúsculas. ¿Cómo puedo hacer un case-insensitive de búsqueda?

He encontrado una forma de hacerlo:

Query.Matches(
    "FirstName", 
    BsonRegularExpression.Create(new Regex(searchKey,RegexOptions.IgnoreCase)));

10 Comentarios

  1. 63

    La forma más simple y segura de hacerlo es utilizando Linq:

    var names = namesCollection.AsQueryable().Where(name =>
        name.FirstName.ToLower().Contains("hamster"));

    Como se explica en el tutorial ToLower, ToLowerInvariant, ToUpper y ToUpperInvariant realizar todos los partidos en un caso insensible manera. Después de que usted puede utilizar toda la cadena compatibles métodos como Contains o StartsWith.

    Este ejemplo se va a generar:

    {
        "FirstName" : /hamster/is
    }

    La i opción hace que sea insensible a mayúsculas-minúsculas.

    • Esta debe ser la respuesta!
    • Estoy de acuerdo.
    • ¿cómo puedes saber si el query utilizando Linq ha encontrado algo o no, yo sólo traté de usarlo, pero no sé si mi condición se cumple o no
    • donde es un filtro. Sólo devuelve lo que pasa a través del filtro y se cumple la condición. Si desea obtener los artículos de sí mismos el uso de un foreach bucle. Si usted quiere saber sólo si documento cumple la condición puede utilizar Cualquier método de extensión.
    • ¿cuál es el resultado si yo uso el any,la he usado antes, como esta col.AsQueryable().Where(x => x._id.ToLower().Contains(input.ToLower)); he intentado utilizar foreach y poner int i = 0; dentro de ella, pero nunca lo golpeó cuando la depuración. El id dentro de mi colección es sushi, y cuando la entrada es Sushi o cualquier variante de inferior o superior del caso, nunca golpear la int i = 0; dentro de la foreach bucle. También he intentado usar .Count() pero siempre dice que 0 para los resultados
    • entonces usted no tiene todos los documentos que satisfacen la condición
    • ¿qué s hacer en /is?
    • el carácter de punto (es decir .) para que coincida con todos los caracteres incluye caracteres de salto de línea.» docs.mongodb.com/manual/reference/operator/query/regex/…

  2. 38

    He implementado esta mucho más simple que cualquiera de las otras sugerencias. Sin embargo me doy cuenta de que debido a la antigüedad de esta pregunta, esta funcionalidad puede no haber estado disponible en el momento.

    Utilizar las opciones de que el Hijo de la Expresión Regular constructor a pasar en caso de falta de sensibilidad. Acabo de mirar el código fuente y se encontró que el ‘yo’ es todo lo que usted necesita. Por ejemplo.

    var regexFilter = Regex.Escape(filter);
    var bsonRegex = new BsonRegularExpression(regexFilter, "i");
    
    Query.Matches("MyField", bsonRegex);

    Usted no debería tener que mantener los registros de dos veces para la búsqueda.

    • ADVERTENCIA: Esto se producirá si el filtro de la cadena que se pasó contiene regex símbolos. Por ejemplo, si usted pasa en una dirección de correo electrónico «[email protected]» devolverá 0 registros de la espalda, debido a que el símbolo»+».
    • Yo estaría encantado de actualizar esta respuesta si alguien puede recomendar una forma de evitar el comentario de @Justin ha hecho. No estoy trabajando con MongoDb en el momento por lo que no es práctico para investigar.
    • Su mejor apuesta sería la de escapar de los personajes en filter con Regex.Escape(filter) a continuación, pasar.
    • no debería ser esto ? var bsonRegex = new BsonRegularExpression(regexFilter, "i");
    • Sin mancha durante 4 años, actualizado @balron
  3. 16

    intentar usar algo como esto:

    Query.Matches("FieldName", BsonRegularExpression.Create(new Regex(searchKey, RegexOptions.IgnoreCase)))
    • no hay problema, pero con cuidado con el índice creado para este campo.
    • Uso /^Nombre»$/i, por encima de consulta partido «WhateverFirstName»
  4. 12

    Usted probablemente tendrá que almacenar el campo dos veces, una vez con su valor real, y de nuevo en minúsculas. A continuación, puede consultar la convertidas a minúsculas versión de mayúsculas y minúsculas de búsqueda (no hay que olvidarse de minúsculas de la cadena de consulta).

    Este enfoque funciona (o es necesario) para muchos sistemas de bases de datos, y se deben de realizar de mejor que regular la expresión de la base de técnicas (al menos por el prefijo o la coincidencia exacta).

    • Que no es una solución práctica de la OMI. La respuesta correcta es aquí. stackoverflow.com/a/8246621/309644
    • Depende. El uso de búsqueda de texto completo viene con sus propias desventajas. Regular B-Árbol de campo indexado puede hacer cosas buenas como las búsquedas de prefijo o ser más fácil de combinar con otros campos, por ejemplo.
  5. 4

    Como i3arnon responde, se puede usar Consultable a hacer un insensible a mayúsculas-minúsculas comparación y búsqueda. Lo que descubrí fue, que no podía usar la cadena.Equals() método, porque no es compatible. Si usted necesita para hacer una comparación, Contiene() lamentablemente no ser adecuado que me mantuvo luchando por una solución, por bastante tiempo.

    Para cualquier persona que quiera hacer una comparación de cadenas, simplemente use == lugar de .Equals().

    Código:

    var names = namesCollection.AsQueryable().Where(name =>
        name.FirstName.ToLower() == name.ToLower());
    • Gracias mucho por esta respuesta. Yo traté de seguir i3arnon la respuesta y siguió corriendo en un error {document}{clave}.ToLower() no es compatible. Resultó ser como usted dijo: es Igual no es compatible.
    • .AsQueryable() siempre convertir su consulta para agregar la tubería, que más lento, de consulta básica
  6. 1

    En caso de que nadie pregunte, utilizando fluidez-mongo add-on, se puede usar Linq para consultar como que:

    public User FindByEmail(Email email)
    {
        return session.GetCollection<User>().AsQueryable()
               .Where(u => u.EmailAddress.ToLower() == email.Address.ToLower()).FirstOrDefault();
    }

    Que se traduce en una correcta JS-consulta. Por Desgracia, La Cadena De Caracteres.Equals() no se admite todavía.

    • Me pregunto cómo funciona internamente? Yo estaba bajo la impresión de que la única manera de hacerlo fueron a través de una expresión regular (que no puede utilizar el índice) y la duplicación del campo.
    • Buscando en las fuentes Que utiliza .método tolowercase() método, nada especial. Pero me tienes preocupado acerca de los índices.
  7. 1

    También puede utilizar MongoDB incorporado en los filtros. Esto puede hacer que sea más fácil para el uso de algunas de mongo métodos.

    var filter = Builders<Model>.Filter.Where(p => p.PropertyName.ToLower().Contains(s.ToLower()));
    var list = collection.Find(filter).Sort(mySort).ToList();
  8. 0

    Una manera de hacerlo es usar MongoDB.Bson.BsonJavaScript clase como se muestra a continuación

     store.FindAs<Property>(Query.Where(BsonJavaScript.Create(string.Format("this.City.toLowerCase().indexOf('{0}') >= 0", filter.City.ToLower()))));
    • Yo podría hacer esto, pero javascript no es capaz de utilizar índices. Así que ser muy lento.
  9. 0

    Para MongoDB 3.4+ la forma recomendada es el uso de índices.
    Ver https://jira.mongodb.org/browse/DOCS-11105?focusedCommentId=1859745&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-1859745

    Estoy con éxito la búsqueda con mayúsculas de minúsculas por:
    1. La creación de un índice con Intercalación de una configuración regional (e.g: «es») y con una fuerza de 1 o 2. Ver https://docs.mongodb.com/manual/core/index-case-insensitive/ para más detalles

    1. Utilizando la misma Intercalación al realizar búsquedas en la MongoDb colección.

    Como un ejemplo:

    Crear una intercalación con la fuerza de 1 o 2 para no distingue mayúsculas de minúsculas

    private readonly Collation _caseInsensitiveCollation = new Collation("en", strength: CollationStrength.Primary);

    Crear un índice. En mi caso yo índice de varios campos:

    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);
    }

    Al consultar asegúrese de usar la misma Intercalación:

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

Dejar respuesta

Please enter your comment!
Please enter your name here