Pergunta

Exemplo:

> db.stuff.save({"foo":"bar"});

> db.stuff.find({"foo":"bar"}).count();
1
> db.stuff.find({"foo":"BAR"}).count();
0
Foi útil?

Solução

Você pode usar um regex .

No seu exemplo que seria:

db.stuff.find( { foo: /^bar$/i } );

Devo dizer, no entanto, talvez você poderia apenas downcase (ou upcase) o valor sobre o modo como, em vez de incorrer no custo extra cada vez que você encontrá-lo. Obviamente, isso não vai funcionar para os nomes das pessoas e tal, mas talvez casos de uso como tags.

Outras dicas

UPDATE:

A resposta original é agora obsoleta. MongoDB suporta agora avançada pesquisa de texto completo, com muitos recursos.

RESPOSTA ORIGINAL:

Deve-se notar que a pesquisa com maiúsculas e minúsculas de regex / i significa que o MongoDB não pode procurar pelo índice, de modo consultas em grandes conjuntos de dados pode levar um longo tempo.

Mesmo com pequenos conjuntos de dados, não é muito eficiente. Você tomar uma batida cpu muito maior do que os seus mandados de consulta, o que poderia se tornar um problema se você está tentando alcançar escala.

Como alternativa, você pode armazenar uma cópia em maiúsculas e pesquisa contra isso. Por exemplo, eu tenho uma tabela de usuário que tem um nome de usuário que é maiúsculas e minúsculas, mas o ID é uma cópia em maiúsculas do nome de usuário. Esta duplicação garante case-sensitive é impossível (tendo ambos "Foo" e "foo" não será permitido), e eu posso pesquisar por id = username.toUpperCase () para obter uma busca case-insensitive de nome de usuário.

Se o seu campo é grande, como um corpo da mensagem, duplicação de dados provavelmente não é uma boa opção. Eu acredito usando um indexador estranho como o Apache Lucene é a melhor opção nesse caso.

Tenha em mente que o exemplo anterior:

db.stuff.find( { foo: /bar/i } );

fará com que cada entradas contendo bar para coincidir com a consulta (bar1, barxyz, openbar), que poderia ser muito perigoso para uma pesquisa de nome de usuário em uma função auth ...

Você pode precisar fazer corresponder apenas o termo de pesquisa usando a sintaxe regexp apropriada como:

db.stuff.find( { foo: /^bar$/i } );

Consulte http://www.regular-expressions.info/ para ajuda de sintaxe para expressões regulares

Se você precisa criar a expressão regular a partir de uma variável, esta é uma maneira muito melhor de fazê-lo: https: // stackoverflow. com / a / 10728069/309514

Você pode então fazer algo como:

var string = "SomeStringToFind";
var regex = new RegExp(["^", string, "$"].join(""), "i");
// Creates a regex of: /^SomeStringToFind$/i
db.stuff.find( { foo: regex } );

Isto tem a vantagem de ser mais ser programática ou você pode obter um aumento de desempenho de compilá-lo antes do tempo se você estiver reutilizando-lo muito.

A partir do MongoDB, a maneira recomendada para realizar pesquisas maiúsculas e minúsculas rápido é usar um Case Índice Insensitive .

Eu, pessoalmente, por e-mail um dos fundadores para agradar começar este trabalho, e ele fez isso acontecer! Foi uma href="https://jira.mongodb.org/browse/SERVER-90" questão no JIRA desde 2009 , e muitos pediram o recurso. Veja como funciona:

Um índice de caso-insensível é feita especificando uma agrupamento com uma força de 1 ou 2. Você pode criar um índice de case-insensitive assim:

db.cities.createIndex(
  { city: 1 },
  { 
    collation: {
      locale: 'en',
      strength: 2
    }
  }
);

Você também pode especificar um agrupamento padrão por coleção quando você criá-los:

db.createCollection('cities', { collation: { locale: 'en', strength: 2 } } );

Em ambos os casos, a fim de utilizar o índice de case-insensitive, você precisa especificar o mesmo agrupamento na operação find que foi usado durante a criação do índice ou a coleção:

db.cities.find(
  { city: 'new york' }
).collation(
  { locale: 'en', strength: 2 }
);

Isso irá retornar "New York", "Nova Iorque", "New York" etc.

Outras notas

  • As respostas sugerem a utilização pesquisa de texto completo está errado , neste caso (e potencialmente perigoso ). A questão era sobre como fazer uma consulta de maiúsculas e minúsculas, por exemplo username: 'bill' BILL correspondência ou Bill, não uma consulta de pesquisa de texto completo, que também iria corresponder resultou palavras de bill, como Bills, billed etc.
  • As respostas sugerem usar expressões regulares são lentos, porque mesmo com os índices, a estados de documentação :

    "Caso consultas insensível expressões regulares geralmente não podem usar índices de forma eficaz. A implementação $ regex não é agrupamento-aware e é incapaz de utilizar índices insensíveis ao caso."

    respostas $regex também corre o risco de entrada do usuário injeção .

db.zipcodes.find({city : "NEW YORK"}); // Case-sensitive
db.zipcodes.find({city : /NEW york/i}); // Note the 'i' flag for case-insensitivity

TL; DR

maneira correta de fazer isso em mongo

Não use RegExp

indexação embutido de Go mongodb natural e uso, pesquisa

Passo 1:

db.articles.insert(
   [
     { _id: 1, subject: "coffee", author: "xyz", views: 50 },
     { _id: 2, subject: "Coffee Shopping", author: "efg", views: 5 },
     { _id: 3, subject: "Baking a cake", author: "abc", views: 90  },
     { _id: 4, subject: "baking", author: "xyz", views: 100 },
     { _id: 5, subject: "Café Con Leche", author: "abc", views: 200 },
     { _id: 6, subject: "Сырники", author: "jkl", views: 80 },
     { _id: 7, subject: "coffee and cream", author: "efg", views: 10 },
     { _id: 8, subject: "Cafe con Leche", author: "xyz", views: 10 }
   ]
)

Passo 2:

necessidade de criar índice em qualquer texto campo que deseja procurar, sem consulta indexação será extremamente lenta

db.articles.createIndex( { subject: "text" } )

Passo 3:

db.articles.find( { $text: { $search: "coffee",$caseSensitive :true } } )  //FOR SENSITIVITY
db.articles.find( { $text: { $search: "coffee",$caseSensitive :false } } ) //FOR INSENSITIVITY
db.company_profile.find({ "companyName" : { "$regex" : "Nilesh" , "$options" : "i"}});

Mongo (atual versão 2.0.0) não permite pesquisas maiúsculas e minúsculas contra campos indexados - veja sua documentação. Para os campos não-indexados, as expressões regulares listados em outras respostas deve ser fino.

O melhor método é no idioma de sua escolha, ao criar um invólucro de modelo para seus objetos, ter o seu save () método iterate através de um conjunto de campos que você vai estar procurando em que também são indexados; aqueles conjunto de campos deve ter contrapartes minúsculas que são então usados ??para pesquisa.

Cada vez que o objeto é salvo novamente, as propriedades minúsculas são então verificado e atualizado com quaisquer alterações às propriedades principais. Isto irá torná-lo assim que você pode pesquisar de forma eficiente, mas ocultar o trabalho extra necessário para atualizar o lc campos cada vez.

Os campos minúsculas poderia ser uma chave: armazenamento de objetos de valor ou apenas o nome do campo com uma LC_ prefixado. I utilizar a segunda uma consulta para simplificar (consulta objecto profunda pode ser confuso no vezes).

Nota: você deseja indexar os campos LC_, não os principais campos que são baseados fora.

Suponha que você deseja pesquisar "coluna" em "Tabela" e você quer caso de busca insenstive. A melhor e eficiente maneira é como abaixo;

//create empty JSON Object
mycolumn = {};

//check if column has valid value
if(column) {
    mycolumn.column = {$regex: new RegExp(column), $options: "i"};
}
Table.find(mycolumn);

código acima só aumenta o seu valor de pesquisa como RegEx e pesquisas com critérios estabelecidos insensitve com "i" como opção.

Todo o melhor.

Uma coisa muito importante manter em mente quando se utiliza uma consulta com base Regex - Quando você está fazendo isso por um sistema de login, escapar cada personagem você está procurando, e não se esqueça o ^ e $ operadores. Lodash tem uma função agradável para este , você deve usá-lo já:

db.stuff.find({$regex: new RegExp(_.escapeRegExp(bar), $options: 'i'})

Por quê? Imagine um .* entrada do usuário como seu nome de usuário. Que iria coincidir com todos os nomes de usuário, permitindo um login por apenas adivinhar a senha de qualquer usuário.

Usando Mongoose isso funcionou para mim:

var find = function(username, next){
    User.find({'username': {$regex: new RegExp('^' + username, 'i')}}, function(err, res){
        if(err) throw err;
        next(null, res);
    });
}

O quadro de agregação foi introduzido em MongoDB 2.2. Você pode usar o operador string "$ strcasecmp" para fazer uma comparação de maiúsculas e minúsculas entre as cordas. É mais recomendado e mais fácil do que usando regex.

Aqui está o documento oficial sobre o operador de comando agregação: https://docs.mongodb.com/manual/reference/operator/aggregation/strcasecmp/#exp._S_strcasecmp .

Você pode usar Índices maiúsculas e minúsculas :

O exemplo a seguir cria uma coleção sem intercalação padrão, em seguida, adiciona um índice no campo de nome com um agrupamento diferencia maiúsculas de minúsculas. International Components for Unicode

/* strength: CollationStrength.Secondary
* Secondary level of comparison. Collation performs comparisons up to secondary * differences, such as diacritics. That is, collation performs comparisons of 
* base characters (primary differences) and diacritics (secondary differences). * Differences between base characters takes precedence over secondary 
* differences.
*/
db.users.createIndex( { name: 1 }, collation: { locale: 'tr', strength: 2 } } )

Para usar o índice, as consultas devem especificar o mesmo agrupamento.

db.users.insert( [ { name: "Oğuz" },
                            { name: "oğuz" },
                            { name: "OĞUZ" } ] )

// does not use index, finds one result
db.users.find( { name: "oğuz" } )

// uses the index, finds three results
db.users.find( { name: "oğuz" } ).collation( { locale: 'tr', strength: 2 } )

// does not use the index, finds three results (different strength)
db.users.find( { name: "oğuz" } ).collation( { locale: 'tr', strength: 1 } )

ou você pode criar uma coleção com agrupamento padrão:

db.createCollection("users", { collation: { locale: 'tr', strength: 2 } } )
db.users.createIndex( { name : 1 } ) // inherits the default collation

Para pesquisar uma variável e escapar dela:

const escapeStringRegexp = require('escape-string-regexp')
const name = 'foo'
db.stuff.find({name: new RegExp('^' + escapeStringRegexp(name) + '$', 'i')})   

Escapando a variável protege a consulta contra ataques com '*' ou outro regex.

escapar-string-regexp

Eu criei um simples Func para o regex caso insensível, que eu uso no meu filtro.

private Func<string, BsonRegularExpression> CaseInsensitiveCompare = (field) => 
            BsonRegularExpression.Create(new Regex(field, RegexOptions.IgnoreCase));

Então você simplesmente filtro em um campo da seguinte forma.

db.stuff.find({"foo": CaseInsensitiveCompare("bar")}).count();

Usando um filtro funciona para mim em C #.

string s = "searchTerm";
    var filter = Builders<Model>.Filter.Where(p => p.Title.ToLower().Contains(s.ToLower()));
                var listSorted = collection.Find(filter).ToList();
                var list = collection.Find(filter).ToList();

Pode até usar o índice, porque eu acredito que os métodos são chamados após o retorno acontece, mas eu não testei isso ainda.

Isso também evita um problema de

var filter = Builders<Model>.Filter.Eq(p => p.Title.ToLower(), s.ToLower());

que mongodb vai pensar p.Title.ToLower () é uma propriedade e não irá mapear corretamente.

Para qualquer um usando golang e desejos de ter caso pesquisa de texto completo sensível com MongoDB e do mgo GoDoc GlobalSign biblioteca .

collation := &mgo.Collation{
    Locale:   "en",
    Strength: 2, 
}


err := collection.Find(query).Collation(collation)

Use RegExp , No caso, se todas as outras opções não funcionam para você, RegExp é uma boa opção. Isso torna o caso insensível string.

var username = new RegExp("^" + "John" + "$", "i");;

Usar nome de usuário em consultas e, em seguida, o seu feito.

Espero que ele vai trabalhar para você também. Todo o melhor.

Como você pode ver na docs mongo - uma vez que o índice versão 3.2 $text é case-insensitive por padrão: https://docs.mongodb.com/manual/core/index-text/#text-index-case-insensitivity

Criar um índice de texto e < a href = "https://docs.mongodb.com/manual/reference/operator/query/text/#op._S_text" rel = "nofollow noreferrer"> usar $ operador de texto em sua consulta .

Estes foram testados para pesquisas de cadeia

{'_id': /.*CM.*/}               ||find _id where _id contains   ->CM
{'_id': /^CM/}                  ||find _id where _id starts     ->CM
{'_id': /CM$/}                  ||find _id where _id ends       ->CM

{'_id': /.*UcM075237.*/i}       ||find _id where _id contains   ->UcM075237, ignore upper/lower case
{'_id': /^UcM075237/i}          ||find _id where _id starts     ->UcM075237, ignore upper/lower case
{'_id': /UcM075237$/i}          ||find _id where _id ends       ->UcM075237, ignore upper/lower case

Eu havia enfrentado um problema semelhante e isto é o que funcionou para mim:

  const flavorExists = await Flavors.findOne({
    'flavor.name': { $regex: flavorName, $options: 'i' },
  });
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top