# PHP MySql - Ähnlichkeitssuche (Meinten Sie...)



## String (26. Mai 2010)

Hallo zusammen,

ich versuche mich nun schon seit einiger Zeit an einer halbwegs verwendbaren Ähnlichkeitssuche.
Also ich habe in einer MySql-Tabelle einige (um genau zu sein 81.000) Wörter stehen, ein Index meiner Suche.

Diese wollte ich irgendwie nutzen um den Usern bei Tippfehlern (oder sowas) ala Google ein "Meinten Sie.." an zu bieten.

Versucht habe ich es mit Levenshtein (viel zu performance lastig - da alle Wörter immer mit allen eingegebenen Suchbegriffen vergleichen werden müssen).
Soundex scheidet auch aus,da es a) für die Englische Sprache gedacht ist b) ein Wort ala "y0551" einfach unter "y0000" gespeichert wird 3) es immer einen Richtigen Anfangsbuchstaben voraussetzt.

Habt ihr da ein paar Suchbegriffen mit denen ich es mal versuche kann?
Oder sogar ein paar Ideen - oder habt ihr es sogar schonmal erstellt?

Bin für jede Hilfe sehr dankbar!

Gruß


----------



## Flex (26. Mai 2010)

Wie wäre es mit einer MySQL Volltextsuche?


----------



## String (27. Mai 2010)

Felix Jacobi hat gesagt.:


> Wie wäre es mit einer MySQL Volltextsuche?



Hilft mir leider nicht weiter. Die Volltextsuche findet z.b. "kupplungsflansch" wenn ich "kupplungflanch" eingebe nicht!?


----------



## Robbz (19. März 2012)

Hier steht was Gutes dazu beschrieben: http://www.internet-magazin.de/ratgeber/fuzzy-suche-mit-php-150630.html#

Ich verwende momentan "SELECT * FROM x WHERE a SOUNDS LIKE '%$searchword%'" aber der findet natürlich nur phonetisch ähnliche Begriffe.
Ich denke mit einem Index über die Levenstein-Distanz oder mittels similar_string() könntest du was erreichen. Allerdings dann nicht mit der DB sondern per PHP. Aber was zählt ist das Ergebnis beim User und nicht der Weg, oder?


----------



## aGeNET (20. März 2012)

viel zu spät gesehen, das Robbz nen uralten Fred ausgekramt hat -.-
aber vielleicht hilfts ja trotzdem jemandem


Hallo String,

ich kann die für dendeutschen Sprachraum eigentlich nur die http://de.wikipedia.org/wiki/Kölner_Phonetik empfehlen. Der Trick an der ganzen Geschichte ist, dass du die gespeicherten Suchwörter zusätzlich als zahlencodierten String in der DB ablegst und dann den eingegebenen Suchbegriff ebenfalls in eine Zahl umwandelst und diese dann zb per LIKE in der DB suchst.

Als Zugabe ne kleine Klasse, die das Arbeiten wesentlich vereinfacht:

```
<?php
class cologne {
	var $rules = array(
		array('/[aejiouy\xC4\xD6\xDC\xE4\xF6\xFC]/i', '0'),
		array('/[b]/i', '1'),
		array('/[p][^h]/i', '1'),
		array('/[dt]([csz])/i', '8$1'),
		array('/[dt](?<=[^csz])/i', '2$1'),
		array('/[fvw]/i', '3'),
		array('/p([h]?)/i', '3$1'),
		array('/[gkq]/i', '4'),
		array('/^c([ahkloqrux])/i', '4$1'),
		array('/([^sz])c([ahkoqux])/i', '${1}4$2'),
		array('/([^ckq]****)x/i', '${1}48'),
		array('/[l]/i', '5'),
		array('/[mn]/i', '6'),
		array('/[r]/i', '7'),
		array('/([sz])c/i', '${1}8'),
		array('/[sz\xDF]/i', '8'),
		array('/^c([^ahkloqrux]****)/i', '8$1'),
		array('/c([^ahkoqux]****)/i', '8$1'),
		array('/([ckq])x/i', '${1}8'),
		array('/[h]/i', '')
	);

	function cologne() {}

	function &getInstance() {
		static $instance;
		if(!is_object($instance) ) {
			$instance = new cologne();
		}
		return $instance;
	}

	function stringCompare($string1, $string2) {
		return $this->compare($string1, $string2);
	}

	function stringEncode($string) {
		return $this->encode($string);
	}

	function compare($string1, $string2) {
		if ($string1 == $string2 || strtolower($string1) === strtolower($string2)) {
			return "eq"; // identisch
		}
		if ($this->encode($string1) === $this->encode($string2)) {
			return "si"; // ähnlich
		}
		return false;
	}

	function encode($string) {
		$string = preg_replace('/[^a-z\xC4\xD6\xDC\xDF\xE4\xF6\xFC]/i', '', $string);
		$string = $this->applyRules($string);
		$string = $this->stripDoubles($string);
		$string = $this->stripZeros($string);
		return $string;
	}

	function applyRules($string) {
		foreach ($this->rules as $rule) {
			$string = preg_replace($rule[0], $rule[1], $string);
		}
		return $string;
	}

	function stripDoubles($string) {
		for ($i = 0; $i <= 9; $i++) {
			$string = preg_replace('/['.$i.']{2}/', $i, $string);
		}
		return $string;
	}

	function stripZeros($string) {
		$first = '';
		if ($string[0] === '0') {
			$first = '0';
			$string = substr($string, 1);
		}
		return $first.preg_replace('/[0]/', '', $string);
	}
}
?>
```

Verwendungsbeispiel:

```
// phonetische Suche
$cologne =& cologne::getInstance();
$search = explode(" ", $searchstring); // $searchstring ist der Suchstring
$suggest_sql = '';
foreach ($search as $break) {
	$suggest_sql.= " OR `field` = '".$cologne->stringEncode($break)."'";
}
$suggest_sql = substr($suggest_sql, 4);
// SELECT * FROM `table` WHERE ($suggest_sql);
// ... weitere Bearbeitung der SQL-Ergebnismenge
```

edith sagt:
der BB-Code zerschiesst irgendwie die RegEx, daher die Klasse als Anhang


----------

