Ü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?

Antworten:


693

Sie können dies mit dem folgenden Code tun.

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

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


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

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.

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.


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.


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

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

Regexes müssen bereinigt werden.
Sean


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.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.