Frage

Beispiel:

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

> db.stuff.find({"foo":"bar"}).count();
1
> db.stuff.find({"foo":"BAR"}).count();
0
War es hilfreich?

Lösung

Sie können eine regex .

In Ihrem Beispiel, das wäre:

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

Ich muss sagen, obwohl, vielleicht könnten Sie einfach downcase (oder upcase) der Wert auf dem Weg in anstatt die zusätzlichen Kosten jedes Mal entstehen Sie es finden. Offensichtlich ist dies nicht funktionieren für Menschen, die Namen und so, aber vielleicht Use-Cases wie Tags.

Andere Tipps

UPDATE:

Die ursprüngliche Antwort ist jetzt veraltet. MongoDB unterstützt jetzt erweiterte Volltextsuche, mit vielen Funktionen.

ORIGINAL ANTWORT:

Es sollte mit regex Fall der Suche beachtet werden, unempfindlich / i bedeuten, dass mongodb nicht durch den Index suchen, so Abfragen für großen Datensätze eine lange Zeit in Anspruch nehmen können.

Selbst bei kleinen Datenmengen, ist es nicht sehr effizient. Sie nehmen eine weit größere CPU-Hit als Ihre Anfrage garantiert, die ein Problem werden könnte, wenn Sie Skala zu erreichen versuchen.

Als Alternative können Sie eine Groß Kopie speichern und gegen diesen suchen. Zum Beispiel habe ich eine Benutzertabelle, die einen Benutzernamen hat, der Fall gemischt wird, aber die ID ist ein Groß Kopie des Benutzernamen ein. Dadurch wird sichergestellt, Groß- und Duplikation unmöglich ist (mit sowohl „Foo“ und „foo“ nicht erlaubt ist), und ich kann mit id = username.toUpperCase () Suche Groß- und Kleinschreibung Suche nach Benutzernamen zu erhalten.

Wenn Ihr Feld ist groß, wie ein Nachrichtentext, Duplizieren von Daten ist wahrscheinlich keine gute Option. Ich glaube, ein Fremd Indexer wie Apache Lucene ist die beste Option in diesem Fall.

Beachten Sie, dass das vorherige Beispiel:

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

bewirkt, dass alle Einträge mit bar die Abfrage (bar1, barxyz, openbar) entsprechen, könnte es für einen Benutzernamen Suche auf einer Auth-Funktion sehr gefährlich sein ...

Unter Umständen müssen Sie es mit Hilfe der entsprechenden regexp-Syntax als nur den Suchbegriff machen entsprechen:

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

Siehe http://www.regular-expressions.info/ für Syntax-Hilfe zu regulären Ausdrücken

Wenn Sie den regulären Ausdruck aus einer Variablen erstellen müssen, ist dies ein viel besserer Weg, es zu tun: https: // Stackoverflow. com / a / 10728069/309514

Sie können dann so etwas wie:

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

Dies hat den Vorteil mehr programmatische werden wird, oder Sie können eine Leistungssteigerung erhalten, indem sie vor der Zeit kompilieren, wenn Sie es viel sind die Wiederverwendung.

Beginnend mit MongoDB, die empfohlene Art und Weise schnell Groß- und Kleinschreibung Suchen durchzuführen ist, ein Case Insensitive Index .

Ich mailte persönlich einer der Gründer diese Arbeit zu gefallen zu bekommen, und er machte es möglich! Es war ein Ausgabe auf JIRA seit 2009 , und viele haben die Funktion angefordert. Hier ist, wie es funktioniert:

Ein Groß- und Kleinschreibung Index wird durch die Angabe eines Sortierungs mit einer Stärke von entweder 1 oder 2. Sie können einen Groß- und Kleinschreibung Index wie folgt erstellen:

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

Sie können auch eine Standardsortierung pro Sammlung angeben, wenn Sie sie erstellen:

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

In jedem Fall, um den Groß- und Kleinschreibung Index zu verwenden, müssen Sie die gleiche Sortierung in der find Operation angeben, die verwendet wurde, als den Index oder die Sammlung zu erstellen:

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

Dies wird zurückkehren "New York", "New York", "New York" etc.

Andere Anmerkungen

  • Die Antworten zu verwenden, was darauf hindeutet, Volltextsuche sind falsch in diesem Fall (und möglicherweise gefährlich ). Die Frage war, über einen Fall unempfindliche Abfrage machen, z.B. username: 'bill' passender BILL oder Bill, keine Volltextsuchabfrage, die passen würde auch dämmt Worte bill, wie Bills, billed etc.
  • Die Antworten darauf hindeutet, reguläre Ausdrücke langsam, mit Indizes, die Dokumentation Zustände :

      

    „Groß- und Kleinschreibung für reguläre Ausdrücke Abfragen im Allgemeinen nicht Indizes effektiv nutzen können. Die $ Regex-Implementierung ist nicht Kollatierungsname bewusst und ist nicht in der Lage Groß- und Kleinschreibung Indizes zu nutzen.“

    $regex Antworten auch die Gefahr von Benutzereingabe Injektion .

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

TL; DR

richtiger Weg, dies in Mongo zu tun

Sie nicht mit RegExp

gehen natürliche und mongodb der eingebauten Indizierung, Suche

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

Schritt 2:

Sie benötigen Index zu schaffen, auf welcher auch immer TEXT Sie suchen mögen, ohne Indizierung Abfrage wird extrem langsam sein

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

Schritt 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 (aktuelle Version 2.0.0) erlaubt keine Groß- und Kleinschreibung Suchvorgänge indizierte Felder - siehe ihre Dokumentation . Für nicht-indizierten Felder, die regulären Ausdrücke in den anderen Antworten aufgeführt ist, sollen in Ordnung sein.

Die beste Methode, in der Sprache Ihrer Wahl ist, wenn ein Modell Wrapper für Ihre Objekte zu schaffen, haben Ihre save () -Methode durch eine Reihe von Feldern durchlaufen, die Sie auf der Suche sein werden, die auch indiziert ist; jene Gruppe von Feldern sollten Kleinbuchstaben haben, die dann verwendet werden, für die Suche.

Jedes Mal wenn das Objekt wieder gespeichert wird, werden die Kleinen Eigenschaften dann überprüft und mit den Änderungen zu den wichtigsten Eigenschaften aktualisiert. Dadurch wird es, so dass Sie effizient suchen können, aber verstecken die zusätzliche Arbeit notwendig, um die LC-Felder jedes Mal zu aktualisieren.

Die unteren Felder Fall könnte ein Schlüssel sein: Wert Objektspeicher oder nur der Feldname mit einem Präfix LC_. Ich benutze die zweite zu vereinfachen Abfragen (tiefe Objekt anfragende kann manchmal verwirrend sein).

Hinweis: Sie indizieren möchten die LC_ Felder, nicht die Hauptbereiche sie basieren aus der.

Angenommen, Sie in „Tabelle“ suchen, „Spalte“ wollen, und Sie wollen Fall insenstive suchen. Der beste und effizienteste Weg ist, wie unten;

//create empty JSON Object
mycolumn = {};

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

über Code nur fügt Ihren Suchwert als RegEx und sucht mit unempfindlich Kriterien mit „i“ als Option.

Alles Gute.

Eine sehr wichtige Sache im Auge zu behalten, wenn eine Regex Abfrage verwenden - Wenn Sie dies für ein Login-System tun, jedes einzelne Zeichen entkommen Sie suchen, und nicht zu vergessen die ^ und $ Operatoren. Lodash eine nette Funktion für diese hat, sollten Sie es schon werden:

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

Warum? Stellen Sie sich einen Benutzer Eingabe .* als seine Benutzername ein. Das würde alle Benutzernamen übereinstimmen, so dass eine Anmeldung nur durch jeden Anwender Passwort zu erraten.

Mit Mongoose dies für mich gearbeitet:

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

Der Aggregations Rahmen wurde in mongodb 2.2 eingeführt. Sie können den String-Operator „$ strcasecmp“ verwenden, um einen Groß- und Kleinschreibung Vergleich zwischen Strings zu machen. Es ist mehr empfohlen und einfacher als regex.

Hier ist das offizielle Dokument, auf dem Aggregations Befehl Operator: https://docs.mongodb.com/manual/reference/operator/aggregation/strcasecmp/#exp._S_strcasecmp .

Sie können Case Insensitive Indizes :

Im folgenden Beispiel wird eine Sammlung ohne Standardsortierung, dann mit einem Fall insensitive Sortierung einen Index für das Namensfeld hinzufügt. 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 } } )

den Index zu verwenden, Abfragen die gleiche Zusammenstellung angeben müssen.

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

oder Sie können eine Sammlung mit Standardsortierung erstellen:

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

Für eine Variable suchen und Entkommen:

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

die Variable Escaping schützt die Abfrage gegen Angriffe mit ‚*‘ oder anderen Regex.

entkommen-string-regexp

Ich habe ein einfaches Func für das Groß- und Kleinschreibung Regex erstellt, die ich in meinem Filter verwenden.

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

Dann einfach Sie auf einem Feld wie folgt filtern.

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

Mit einem Filter funktioniert für mich 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();

Es kann sogar den Index verwenden, weil ich die Methoden glaube aufgerufen werden nach der Rückkehr passiert, aber ich habe das noch nicht getestet werden.

Dies vermeidet auch ein Problem von

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

, dass mongodb denken p.Title.ToLower () eine Eigenschaft ist und nicht richtig zugeordnet werden.

Wie Sie in Mongo docs sehen - seit Version 3.2 $text Index ist Groß- und Kleinschreibung standardmäßig: https://docs.mongodb.com/manual/core/index-text/#text-index-case-insensitivity

Erstellen eines Textindex und < a href = "https://docs.mongodb.com/manual/reference/operator/query/text/#op._S_text" rel = "nofollow noreferrer"> Verwendung $ text Operator in Ihrer Anfrage .

Diese sind für String-Suche getestet

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

ich ein ähnliches Problem konfrontiert war, und das ist, was für mich gearbeitet:

  const flavorExists = await Flavors.findOne({
    'flavor.name': { $regex: flavorName, $options: 'i' },
  });
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top