Überprüfen, ob ein Feld eine Zeichenfolge enthält

454

Ich suche einen Operator, mit dem ich überprüfen kann, ob der Wert eines Feldes eine bestimmte Zeichenfolge enthält.

Etwas wie:

db.users.findOne({$contains:{"username":"son"}})

Ist das möglich?

Johnny
quelle

Antworten:

693

Sie können dies mit dem folgenden Code tun.

db.users.findOne({"username" : {$regex : ".*son.*"}});
Parvin Gasimzade
quelle
16
Beachten Sie, dass dies einen Index nicht effizient nutzt und dazu führt, dass alle Werte nach Übereinstimmungen durchsucht werden. Siehe die Hinweise zu regulären Ausdrücken
Stennie
7
@Stennie, was schlagen Sie dann vor, um den Index effizient zu nutzen und einen Teilstring zu finden?
Blue Sky
4
@Vish: Wenn Ihr häufiger Anwendungsfall die Freitextsuche in einem Feld ist und Sie über eine große Anzahl von Dokumenten verfügen, würde ich den Text für effizientere Abfragen tokenisieren. Sie können Multikeys für eine einfache Volltextsuche verwenden oder einen invertierten Index als separate Sammlung erstellen . Bei seltenen Suchvorgängen oder einer kleinen Sammlung von Dokumenten kann das Scannen des vollständigen Index eine akzeptable (wenn auch nicht optimale) Leistung sein.
Stennie
98
Ist das nicht ein bisschen übertrieben? Was Sie wollen, ist db.users.findOne({"username" : {$regex : "son"}});
JamieJag
3
Vielleicht möchten Sie die Volltextsuche in Mongo 2.6
wprl
179

Da Mongo Shell Regex unterstützt, ist dies durchaus möglich.

db.users.findOne({"username" : /.*son.*/});

Wenn bei der Abfrage die Groß- und Kleinschreibung nicht berücksichtigt werden soll, können Sie die Option "i" verwenden, wie unten gezeigt:

db.users.findOne({"username" : /.*son.*/i});

Siehe: http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-RegularExpressions

James Gan
quelle
1
Bitte fügen Sie ein Code-Snippet bei, das die Verwendung regulärer Ausdrücke für die Suche demonstriert. Die Antworten sollten mehr Informationen als nur einen Link enthalten ...
Maerics
1
Die ausgewählte Antwort hat bei mir nicht funktioniert, aber diese hat funktioniert (ich führe Mongo-Abfragen über Docker-Exec-Befehle aus). Ich denke, diese Antwort sollte die ausgewählte Antwort sein, da sie vielseitiger zu sein scheint.
Arthur Weborg
5
Wie die Kommentare in der ausgewählten Antwort db.users.findOne({"username" : /.*son.*/});könnte es meiner Meinung nach auch übertrieben sein und der /son/
reguläre Ausdruck
2
Prägnanter als die Verwendung von $ regex
Lionet Chen
4
Bearbeiten Sie dies, um es nur zu verwenden{ username: /son/ }
Wyck
150

https://docs.mongodb.com/manual/reference/sql-comparison/

http://php.net/manual/en/mongo.sqltomongo.php

MySQL

SELECT * FROM users WHERE username LIKE "%Son%"

MongoDB

db.users.find({username:/Son/})
Zheng Kai
quelle
8
Ihre MongoDB-Antwort ist gut. Bearbeiten Sie Ihre Frage, um die irrelevanten MySQL-Hinweise zu entfernen.
Maerics
31
Alle Abfragen entfernen oder ändern? Die meisten Leute kennen SQL, es ist hilfreich für das Verständnis von MongoDB
Zheng Kai
4
@ZhengKai: Auf dieser Website sollten Sie die Frage normalerweise direkt beantworten und nur die spezifischen Technologien verwenden, die markiert und angefordert wurden.
Maerics
98
@maerics persönlich Ich fand Zhengs Aufnahme von MySQL sehr nützlich, da es einen Bezugspunkt darstellte.
Mike Bartlett
50
Ich fand auch die SQL-Referenz relevant, ich denke, es sollte bleiben.
Wikingersteve
69

Ab Version 2.4 können Sie einen Textindex für die Felder erstellen, um den $ text- Operator zu suchen und zum Abfragen zu verwenden.

Erstellen Sie zunächst den Index:

db.users.createIndex( { "username": "text" } )

Dann, um zu suchen:

db.users.find( { $text: { $search: "son" } } )

Benchmarks (~ 150.000 Dokumente):

  • Regex (andere Antworten) => 5,6-6,9 Sekunden
  • Textsuche => .164-.201 Sekunden

Anmerkungen:

  • Eine Sammlung kann nur einen Textindex haben. Sie können einen Platzhalter-Textindex verwenden, wenn Sie ein beliebiges Zeichenfolgenfeld wie folgt durchsuchen möchten : db.collection.createIndex( { "$**": "text" } ).
  • Ein Textindex kann groß sein. Es enthält einen Indexeintrag für jedes eindeutige Wort nach dem Stiel in jedem indizierten Feld für jedes eingefügte Dokument.
  • Die Erstellung eines Textindex dauert länger als die eines normalen Index.
  • Ein Textindex speichert keine Phrasen oder Informationen über die Nähe von Wörtern in den Dokumenten. Infolgedessen werden Phrasenabfragen viel effektiver ausgeführt, wenn die gesamte Sammlung in den Arbeitsspeicher passt.
Okoboko
quelle
14
Nein, der Infact-Textoperator erlaubt nicht die Ausführung von "enthält", daher wird nur die exakte Wortübereinstimmung zurückgegeben. Die einzige Option ab 3.0 ist die Verwendung von Regex, dh db.users.find ({Benutzername: / son / i}) ) dieser sucht jeden Benutzer mit "Sohn" (case-insenstive)
comeGetSome
3
Müssen Sie neu indizieren, wenn Sie Dokumente zur Sammlung hinzufügen oder daraus entfernen?
Jake Wilson
Der Titel der Frage lautet "enthält". Die Volltextsuche gilt nicht für die Frage.
Donato
29

Da dies einer der ersten Treffer in den Suchmaschinen ist und keiner der oben genannten Treffer für MongoDB 3.x zu funktionieren scheint, ist hier eine Regex-Suche, die funktioniert:

db.users.find( { 'name' : { '$regex' : yourvalue, '$options' : 'i' } } )

Keine Notwendigkeit, einen zusätzlichen Index oder ähnliches zu erstellen.

Nitai
quelle
1
Regexes müssen bereinigt werden.
Sean
16

Folgendes müssen Sie tun, wenn Sie MongoDB über Python verbinden

db.users.find({"username": {'$regex' : '.*' + 'Son' + '.*'}})

Sie können auch einen Variablennamen anstelle von 'Son' und damit die Zeichenfolgenverkettung verwenden.

Patthebug
quelle
in es2015 können Sie Backticks verwenden {$ regex: .*${value}.*}
Michael Guild
16

Einfachster Weg, um diese Aufgabe zu erfüllen

Wenn Sie möchten, dass bei der Abfrage zwischen Groß- und Kleinschreibung unterschieden wird

db.getCollection("users").find({'username':/Son/})

Wenn Sie möchten, dass bei der Abfrage die Groß- und Kleinschreibung nicht berücksichtigt wird

db.getCollection("users").find({'username':/Son/i})
Anurag Misra
quelle
1
Wie benutzt man eine Variable mit Regex?
Hisham
4

Ideale Antwort auf die Option " Index i verwenden " für Groß- und Kleinschreibung

db.users.findOne({"username" : new RegExp(search_value, 'i') });
Hisham
quelle
Regexes müssen bereinigt werden.
Sean
2

Dies sollte die Arbeit erledigen

db.users.find({ username: { $in: [ /son/i ] } });

Das iist nur da, um Einschränkungen beim Abgleichen einzelner Buchstabenfälle zu verhindern.

Sie können die $ regex-Dokumentation in der MongoDB-Dokumentation überprüfen. Hier ist ein Link: https://docs.mongodb.com/manual/reference/operator/query/regex/

tate
quelle
1

So ignorieren Sie HTML-Tags in einer RegExp-Übereinstimmung:

var text = '<p>The <b>tiger</b> (<i>Panthera tigris</i>) is the largest <a href="https://stackoverflow.com/wiki/Felidae" title="Felidae">cat</a> <a href="https://stackoverflow.com/wiki/Species" title="Species">species</a>, most recognizable for its pattern of dark vertical stripes on reddish-orange fur with a lighter underside. The species is classified in the genus <i><a href="https://stackoverflow.com/wiki/Panthera" title="Panthera">Panthera</a></i> with the <a href="https://stackoverflow.com/wiki/Lion" title="Lion">lion</a>, <a href="https://stackoverflow.com/wiki/Leopard" title="Leopard">leopard</a>, <a href="https://stackoverflow.com/wiki/Jaguar" title="Jaguar">jaguar</a>, and <a href="https://stackoverflow.com/wiki/Snow_leopard" title="Snow leopard">snow leopard</a>. It is an <a href="https://stackoverflow.com/wiki/Apex_predator" title="Apex predator">apex predator</a>, primarily preying on <a href="https://stackoverflow.com/wiki/Ungulate" title="Ungulate">ungulates</a> such as <a href="https://stackoverflow.com/wiki/Deer" title="Deer">deer</a> and <a href="https://stackoverflow.com/wiki/Bovid" class="mw-redirect" title="Bovid">bovids</a>.</p>';
var searchString = 'largest cat species';

var rx = '';
searchString.split(' ').forEach(e => {
  rx += '('+e+')((?:\\s*(?:<\/?\\w[^<>]*>)?\\s*)*)';
});

rx = new RegExp(rx, 'igm');

console.log(text.match(rx));

Dies ist wahrscheinlich sehr einfach in einen MongoDB-Aggregationsfilter umzuwandeln.

Tamás Polgár
quelle