regexp - mehrere Wörter in beliebiger Reihenfolge
Sancho
- programmiertechnik
0 wahsaga0 Alexander Brock0 Sancho
0 Dieter Raber0 Sancho
0 MudGuard
Hallo Experten,
Gibt es einen von mir bisher übersehenen Regexp-modifier bzw. -switch mit dem ich nach _mehreren_ Wörtern suchen kann, die in _beliebiger_ Reihenfolge vorkommen können, wobei aber jedes der Wörter wenigstens einmal vorhanden sein muss?
Beispiel:
Text:
'hans war gestern irgendwie komisch'
gesucht werden:
'gestern'
'komisch'
'hans'
'matchender' (aber sehr umständlicher) regulärer Ausdruck
(und noch ohne Berücksichtigung der Wortgrenzen):
$re = '/(gestern.*komisch.*hans)|(gestern.*hans.*komisch)|(komisch.*gestern.*hans)| (etc.) /'
---
Hintergrund der Frage ist eine MySQL-Tabelle mit _mehreren_ Textfeldern.
Die Suche soll für jeden einzelnen Datensatz genau dann als erfolgreich gelten, wenn der gesuchte reguläre Ausdruck auf alle seine Textfelder _zusammen_ zutrifft.
Dadurch erhöht sich die Verknüpfungsdimension noch zusätzlich; und ich denke mal, dass in so einem Fall eine WHERE-clause der Form:
"WHERE CONCAT_WS(' ', feld1, feld2, feld3) REGEXP '$re'"
die resourcenschonendste Variante ist, denn andernfalls wäre folgendes notwendig:
"WHERE CONCAT_WS(' ', feld1, feld2, feld3) REGEXP '$re1' [ $re1 = '/(^|\W+)gestern($|\W+)/' ]
AND CONCAT_WS(' ', feld1, feld2, feld3) REGEXP '$re2' [ $re2 = '/(^|\W+)komisch($|\W+)/' ]
AND CONCAT_WS(' ', feld1, feld2, feld3) REGEXP '$re3'" [ $re3 = '/(^|\W+)hans($|\W+)/' ]
(Also mehrere CONCAT_WS- und REGEXP-Aufrufe. Ohne REGEXP komme ich auch in diesem Fall nicht aus wegen der Wortgrenzen. Ich kann nämlich nicht
"WHERE CONCAT_WS(' ', feld1, feld2, feld3) LIKE '%hans%'
..."
verwenden, da ja einerseits nicht 'hans' aus '...hansa...' oder '...hanse...' -
andereseits aber 'hans' aus
'... hans ...'
'... hans,...'
'... hans!...'
etc.
sehr wohl gefunden werden soll.)
---
Ich hoffe mein Problem einigermaßen deutlich beschrieben zu haben...
Also nochmal die Frage: Wie läßt sich ein regulären Ausdruck konstruieren, der auf mehrere Wörter in beliebiger Reihenfolge zutrifft? Geht das nur über die Aneinanderreihung aller möglichen Kombinationen - oder gibt es eine andere Möglichkeit?
Grüße,
Sancho
hi,
Hintergrund der Frage ist eine MySQL-Tabelle mit _mehreren_ Textfeldern.
Die Suche soll für jeden einzelnen Datensatz genau dann als erfolgreich gelten, wenn der gesuchte reguläre Ausdruck auf alle seine Textfelder _zusammen_ zutrifft.
Dadurch erhöht sich die Verknüpfungsdimension noch zusätzlich; und ich denke mal, dass in so einem Fall eine WHERE-clause der Form:"WHERE CONCAT_WS(' ', feld1, feld2, feld3) REGEXP '$re'"
die resourcenschonendste Variante ist
na ja, ich würde mir noch mal überlegen, ob nicht eine FULLTEXT SEARCH über alle spalten performanter sein könnte ...
gruß,
wahsaga
Hallo wahsaga,
na ja, ich würde mir noch mal überlegen, ob nicht eine FULLTEXT SEARCH über alle spalten performanter sein könnte ...
gruß,
wahsaga
Stimmt, aber das FULLTEXT SEARCH-Ergebnis informiert mich, soviel ich weiß, nicht genau über das exakte Zutreffen der Suchbedingung sondern ordnet die Ergebnisse nur nach einer 'Relevanz', in deren Interpretation ich ich erst einarbeiten müsste. Hast Du da ev. einen Link parat?
thx,
Sancho
Nochmal hallo wahsaga,
Ahem... sorry für die vielleicht etwas konsternierende Frage nach einem 'paraten' Link...
(Klingt ein wenig nach 'Link bei Fuß'.)
Die MySQL-Doku selbst beispielsweise ist recht dürftig, was die Erläuterungen zu FULL TEXT SEARCH betrifft (siehe http://dev.mysql.com/doc/mysql/de/fulltext-search.html).
Daher nochmal; bist Du vielleicht schonmal irgendwo über einen Link gestolpert, wo diese Funktion, die noch mit einigen TODOs behaftet zu sein scheint, näher erläutert wird?
Würde mir wirklich weiterhelfen...
(Denn den von mir gesuchten regulären Ausdruck gibt es wahrscheinlich nicht. Schade.)
Gruß, Sancho
Hallo Sancho,
Beispiel:
Text:
'hans war gestern irgendwie komisch'gesucht werden:
'gestern'
'komisch'
'hans'
Dazu braucht man doch gar keine Regulären Audrücke, das geht mit
strpos():
$text = 'hans war gestern irgendwie komisch';
$match = array('gestern','komisch','hans');
function match($string,$needle) {
foreach ($needle as $value) {
if (!strpos($string,$value)) return false;
}
return true;
}
Gruß
Alexander Brock
Hallo Alexander,
$text = 'hans war gestern irgendwie komisch';
$match = array('gestern','komisch','hans');function match($string,$needle) {
foreach ($needle as $value) {
if (!strpos($string,$value)) return false;
}
return true;
}
...das bekomme ich aber nicht in die SQL-Abfrage...
Trotzdem Danke.
Gruß, Sancho
Hallo Sancho,
$re = '/(gestern.*komisch.*hans)|(gestern.*hans.*komisch)|(komisch.*gestern.*hans)| (etc.) /'
Wieso nicht einfach ((gestern)|(komisch)|(hans))*
Gruß,
Dieter
Hallo Dieter,
Wieso nicht einfach ((gestern)|(komisch)|(hans))*
Weil das nur ein ODER- und keine UND-Verknüpfung ist.
Gruß, Sancho
Hi,
Gibt es einen von mir bisher übersehenen Regexp-modifier bzw. -switch mit dem ich nach _mehreren_ Wörtern suchen kann, die in _beliebiger_ Reihenfolge vorkommen können, wobei aber jedes der Wörter wenigstens einmal vorhanden sein muss?
Hintergrund der Frage ist eine MySQL-Tabelle mit _mehreren_ Textfeldern.
Muß es ein Regex sein?
Sonst
WHERE spalte LIKE '%hans%' AND spalte LIKE '%gestern%' AND spalte LIKE '%komisch%'
cu,
Andreas
Hi Mudguard,
Muß es ein Regex sein?
SonstWHERE spalte LIKE '%hans%' AND spalte LIKE '%gestern%' AND spalte LIKE '%komisch%'
Äh - ja (wie ausgeführt). Weil ich eben gern die Option zur Suche nach Einzelwörtern einbauen würde. Und wie gesagt; Dein Vorschlag liefert mir auch die nicht gesuchten 'hanse-kogge' 'hängestern'. (Zweites Beispiel ist zugegebenermaßen ewtas 'gesucht'.)
Ich hätte damit also das Problem nur auf die Auswertung des Query-Ergebnisses 'verschoben'.
Wobei sich, da hast Du schon recht, die Anzahl der regex-Aufrufe dadurch natürlich reduzieren läßt;
aber ich wage zu bezweifeln, dass
30 mal mysql:LIKE [bei 10 Zeilen mit 3 gesuchten Wörtern]
und dann ggf.
3 mal PHP:preg_match() [auf 3 Ergebnisse]
performanter ist als
10 mal mysql:REGEX [bei besagten 10 Zeilen]
Aber wie gesagt; mein Denkfehler scheint in der Suche nach einem regulären Ausdruck mit UND-Verknüpfung für Wörter zu liegen. Das scheint tatsächlich nur über die Aneinaderreihung aller Kombinationen zu gehen; und dann hat es spätestens ab 4 Wörtern wohl keinen Zweck mehr.
cu2,
Sancho.
use Mosche;
WHERE spalte LIKE '%hans%' AND spalte LIKE '%gestern%' AND spalte LIKE '%komisch%'
Äh - ja (wie ausgeführt). Weil ich eben gern die Option zur Suche nach Einzelwörtern einbauen würde. Und wie gesagt; Dein Vorschlag liefert mir auch die nicht gesuchten 'hanse-kogge' 'hängestern'. (Zweites Beispiel ist zugegebenermaßen ewtas 'gesucht'.)
Warum? Auf das Suchergebnis trifft "spalte LIKE '%gestern%'" ja nicht zu, und die Bedingungen sind (wie gefordert) mit UND-verknüpft.
Oder steh ich auf dem sprichwörtlichen Schlauch?
use Tschoe qw(Matti);