Domanda

Esempio:

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

> db.stuff.find({"foo":"bar"}).count();
1
> db.stuff.find({"foo":"BAR"}).count();
0
È stato utile?

Soluzione

È possibile utilizzare un regex .

Nel tuo esempio, che sarebbe:

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

Devo dire, però, forse si può solo downcase (o upcase) il valore sul modo in piuttosto che incorrere il costo aggiuntivo ogni volta a trovarlo. Ovviamente questo non funzionerà per i nomi delle persone e così, ma forse uso a casi come tag.

Altri suggerimenti

UPDATE:

La risposta originale è ormai obsoleto. MongoDB supporta ora avanzato la ricerca testo completo, con molte caratteristiche.

RISPOSTA ORIGINALE:

Si deve notare che la ricerca con il caso di regex insensitive / I significa che MongoDB non può cercare per indice, quindi le query di grandi insiemi di dati può richiedere molto tempo.

Anche con piccoli insiemi di dati, non è molto efficiente. Si prende una CPU molto più grande di quanto colpito i vostri mandati di query, che potrebbe diventare un problema se si sta cercando di ottenere in scala.

In alternativa, è possibile memorizzare una copia maiuscola e la ricerca contro questo. Per esempio, ho una tabella utente che ha un nome utente che viene mescolato caso, ma l'ID è una copia maiuscola del nome utente. Questo assicura la duplicazione tra maiuscole e minuscole è impossibile (avendo entrambi "Foo" e "foo" non sarà permesso), e posso cercare per id = username.toUpperCase () per ottenere una ricerca case-insensitive per nome utente.

Se il campo è grande, come ad esempio un corpo del messaggio, di duplicazione di dati non è probabilmente una buona opzione. Credo che utilizza un indicizzatore estranea come Apache Lucene è la migliore opzione in questo caso.

Tenete a mente che l'esempio precedente:

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

causerà ogni voci contenente bar in modo che corrisponda alla query (bar1, barxyz, openbar), potrebbe essere molto pericoloso per una ricerca nome utente su una funzione auth ...

Potrebbe essere necessario farlo corrispondere solo il termine di ricerca utilizzando la sintassi regexp appropriata come:

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

http://www.regular-expressions.info/ aiuto sintassi sulle espressioni regolari

Se è necessario creare l'espressione regolare da una variabile, questo è un modo molto migliore per farlo: https: // StackOverflow. COM / a / 10728069/309514

È quindi possibile fare qualcosa di simile:

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

Questo ha il vantaggio di essere più essere programmatico oppure si può ottenere un incremento delle prestazioni mediante la compilazione prima del tempo se si sta riutilizzando un sacco.

A partire MongoDB, il metodo consigliato per eseguire ricerche veloci case-insensitive è quello di utilizzare un Case Insensitive Indice .

Io personalmente contattato uno dei fondatori di compiacere ottenere questo lavoro, e ha fatto accadere! E 'stato un problema su JIRA dal 2009 , e molti hanno chiesto la funzione. Ecco come funziona:

Un indice-insensitive caso è discusso specificando un collazione con una forza di 1 o 2. È possibile creare un indice di case-insensitive in questo modo:

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

È inoltre possibile specificare regole di confronto di default per la raccolta al momento della creazione:

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

In entrambi i casi, al fine di utilizzare l'indice case-insensitive, è necessario specificare lo stesso collazione nell'operazione find che è stato utilizzato durante la creazione dell'indice o della raccolta:

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

Questo restituirà "New York", "New York", "New York", ecc.

Altre note

  • Le risposte che suggeriscono di utilizzare ricerca full-text sono sbagliati in questo caso (e potenzialmente pericoloso ). La domanda era di fare una query case-insensitive, per esempio username: 'bill' corrispondenza BILL o Bill, non una query di ricerca full-text, che sarebbe anche abbinare derivava parole di bill, come Bills, billed etc.
  • Le risposte suggeriscono di usare le espressioni regolari sono lenti, perché anche con gli indici, il stati di documentazione :

      

    "case insensitive query di espressioni regolari in genere non può utilizzare gli indici in modo efficace. L'implementazione $ regex non è la fascicolazione-aware e non è in grado di utilizzare gli indici case-insensitive".

    risposte $regex anche correre il rischio di iniezione di ingresso .

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

TL; DR

modo corretto di fare questo in Mongo

Non utilizzare RegExp

Vai naturale e utilizzare l'indicizzazione integrato di MongoDB, ricerca

Passaggio 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 }
   ]
)

Passaggio 2:

Hai bisogno di creare l'indice su qualunque testo si desidera cercare, senza interrogazione indicizzazione sarà estremamente lento

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

Passaggio 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 (attuale versione 2.0.0) non consente le ricerche case-insensitive contro i campi indicizzati - vedi la loro documentazione . Per i campi non indicizzati, le regex elencati nelle altre risposte dovrebbero andare bene.

Il metodo migliore è nella lingua di propria scelta, quando si crea un modello di wrapper per gli oggetti, avere il vostro metodo save () un'iterazione in un insieme di campi che vi sarà la ricerca su che sono anche indicizzati; quelli stabiliti dei campi dovrebbe avere controparti minuscole che vengono poi utilizzati per la ricerca.

Ogni volta che l'oggetto viene salvato ancora una volta, le proprietà minuscole vengono poi verificato e aggiornato con le eventuali modifiche alle proprietà principali. In questo modo sarà in modo da poter cercare in modo efficiente, ma nascondere il lavoro aggiuntivo necessario per aggiornare i campi lc ogni volta.

I campi minuscole potrebbe essere una chiave: negozio oggetto valore o semplicemente il nome di campo con un LC_ prefissato. Io uso il secondo per semplificare interrogazione (interrogazione oggetto profonda può essere confuso, a volte).

Nota: si vuole indicizzare i campi LC_, non i campi principali si basano fuori di.

Si supponga di voler cercare "colonna" in "Table" e si desidera caso di ricerca insenstive. Il modo migliore ed efficiente è il seguente;

//create empty JSON Object
mycolumn = {};

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

Sopra codice appena aggiunge il valore della ricerca come RegEx e le ricerche con criteri stabiliti insensitve con "i" come opzione.

Tutto il meglio.

Una cosa molto importante da tenere a mente quando si utilizza una query basata Regex - Quando si sta facendo questo per un sistema di login, escape ogni singolo carattere che si sta cercando, e non dimenticate il ^ e $ operatori. Lodash ha una bella funzione per questo , si dovrebbe utilizzare già:

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

Perché? Immaginate un .* entrare utente come il suo nome utente. Che sarebbe abbinare tutti i nomi utente, consentendo un accesso da solo indovinare la password di qualsiasi utente.

Utilizzando Mongoose questo ha funzionato per me:

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

Il quadro di aggregazione è stato introdotto nel MongoDB 2.2. È possibile utilizzare l'operatore di stringa "$ strcasecmp" per fare un confronto tra maiuscole e minuscole tra le stringhe. E 'più consigliabile e più facile che usare espressioni regolari.

Ecco il documento ufficiale per l'operatore di comando di aggregazione: https://docs.mongodb.com/manual/reference/operator/aggregation/strcasecmp/#exp._S_strcasecmp .

È possibile utilizzare Casi Indici Insensitive :

L'esempio seguente crea una collezione senza regole di confronto predefinite, quindi aggiunge un indice sul campo del nome con un caso il confronto maiuscole. 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 } } )

Per utilizzare l'indice, le query devono specificare lo stesso collazione.

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

oppure è possibile creare una collezione con regole di confronto predefinite:

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

Per la ricerca di un variabile e scampo:

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

Sfuggire la variabile protegge la query contro gli attacchi con '*' o altre espressioni regolari.

sfuggire-string-regexp

ho creato un semplice Func per il caso regex insensibile, che uso nel mio filtro.

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

Quindi è sufficiente filtrare su un campo come segue.

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

Utilizzando un filtro funziona per me in 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();

Si può anche utilizzare l'indice, perché credo che i metodi vengono chiamati dopo il ritorno accade, ma non ho ancora testato questo fuori.

Questo evita anche un problema di

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

che MongoDB penseranno p.Title.ToLower () è una proprietà e non mapperà correttamente.

Per uno qualsiasi utilizzando Golang e desidera avere tra maiuscole e minuscole ricerca full text con MongoDB e il MgO GODOC GlobalSign libreria .

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


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

Usa RegExp ,  Nel caso in cui tutte le altre opzioni non funzionano per voi, RegExp è una buona opzione. Rende il caso della stringa insensitive.

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

usare il nome utente nelle query, e quindi il suo fare.

Spero che funzionerà anche per te. Tutto il meglio.

Come si può vedere nella documentazione mongo - in quanto indice di versione 3.2 $text è-case insensitive di default: https://docs.mongodb.com/manual/core/index-text/#text-index-case-insensitivity

creare un indice di testo e < a href = "https://docs.mongodb.com/manual/reference/operator/query/text/#op._S_text" rel = "nofollow noreferrer"> uso $ operatore di testo nella query .

Questi sono stati testati per le ricerche di stringa

{'_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

Avevo affrontato un problema simile e questo è ciò che ha funzionato per me:

  const flavorExists = await Flavors.findOne({
    'flavor.name': { $regex: flavorName, $options: 'i' },
  });
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top