Es gibt nicht so viele Informationen über Sphinx, wie wir möchten. Überschüssiger Artikel tut nicht weh.
Die ersten Schritte bei der Entwicklung von Sphinx haben mir geholfen, die Artikel zu erstellen. Erstellen einer einführenden Suchmaschine für Sphinx + PHP und Sphinx Beispielsuche für ein reales Projekt - Tecdoc Auto Parts Store Ich rate Ihnen, damit zu beginnen.
Für einige Zeit funktionierte eine Suche in LIKE nach jedem Wort der Abfrage auf meiner Website. Ich wollte mehr und hier sind einige Fälle, die jetzt korrekt behandelt werden:
- Wortformen. Die Ausgabe für "Schrauben" und "Schrauben" sollte gleich sein.
- Suche nach Wortfragment.
- Suchen Sie nach nicht ganzzahligen Zahlen. Trennpunkt und Komma.
- Buchstabe y
- Häufige Fehler. Zum Beispiel "Stoßdämpfer".
- Synonyme Regler und Regler.
- Sprache. mAh und mAh, B und V, AAA Latein und Kyrillisch.
- Wort aus Buchstaben und Zahlen. 10 x 15 x 4, 6000 mAh
Quellabschnitt und optionale Sortierung
Die Ausgabe sollte zuerst Artikel auf Lager enthalten, dann vorübergehend fehlen und dann archiviert werden. Alle drei Gruppen sollten nach Relevanz sortiert werden. Dazu müssen Sie die Attribute festlegen. In meinem Fall sind dies die Clearance- und In_stock-Felder des Quellabschnitts sphinx.conf
sql_query = \ SELECT id, `art`, `name`, `clearance`, `in_stock` \ FROM items_zip WHERE show_flag=1 sql_attr_bool = clearance sql_attr_uint = in_stock
Diese Felder werden zum Generieren der Ausgabe in PHP verwendet. Ich werde unten beschreiben.
Indexabschnitt in sphinx.conf
Morphologie = stem_enru
Die Morphologie löst mein erstes Problem. Eine Suche nach "Lagern", "Lagern", "Lagern" führt zu einem einzigen Ergebnis.
Stemms (stem_enru) sind schneller, Lemmas (lemmatize_ru) sind genauer. Ich habe nur stammelt versucht. Die Auswahl wirkt sich auf Ihr Wörterbuch für das Ersetzen von Wortformen aus. Willst du ändern - du musst umschreiben.
min_word_len = 1
Indexwörter beliebiger Länge.
html_strip = 1
Entfernen Sie HTML-Tags
min_infix_len = 1
Die Suche erfolgt nach einem Fragment des Wortes. Indexfragmente bis zu 1 Buchstabe. Da ich weniger als 10.000 Elemente in der Datenbank habe, speichere ich nicht im Index.
expand_keywords = 1
Führt die Abfrage automatisch zum Formular "(running | running | = running)". min_infix_len und expand_keywords führen dazu, dass RV 2205 RV2205 ausgibt. Ein Bindestrich ist übrigens ein Trennzeichen, das einem Leerzeichen entspricht. Der RV-2205 liefert also den gleichen RV2205.
charset_table = 0..9, A..Z-> a..z, _, a..z, U + 410..U + 42F-> U + 430..U + 44F, U + 430..U + 44F, U + 401-> U + 0435, U + 451-> U + 0435
Wir bringen das lateinische Alphabet und das kyrillische Alphabet in Kleinbuchstaben. durch e ersetzen.
blend_chars = +, &, U + 2C, U + 2E
Ich habe viele nicht ganzzahlige Zahlen. Sie müssen vollständig indiziert sein. U + 2C und U + 2E sind ein Punkt und ein Komma. Zum Beispiel wird 1.25 als '1.25', '1' und '25' indiziert.
regexp_filter = (\ d +) \, (\ d +) => \ 1. \ 2
Dezimalstellen in Zahlen können durch Punkte und Kommas getrennt werden: "1,75", "1,75". Wir bringen alles auf den Punkt
Synonyme und Tippfehler
Maßeinheiten können in Russisch oder Englisch geschrieben werden: mm-mm, mAh-mAh, mW-mW. Fügen Sie dem Wörterbuch der Synonyme den Pfad hinzu, zu dem in Wortformen angegeben wird: "mach> mah". Ich wähle die Sprache für den Index nach meinen eigenen Vorlieben.
Das Zeichen ~ zeigt an, dass der Ersatz nach dem Morphologie-Handler angewendet werden soll. Auf diese Weise können Sie nicht alle Wortformen schreiben und anstelle der Regeln für "Kruste", "Kruste", "Kruste" "~ cork> body" schreiben.
Meine Liste ist vollständig:
~ > esc > esc > mah ~ > ~ > ~ > buzz ~ > buzz ~ > buzz ~ > buzz ~ > buzz ~ > ~ > ~ > li-po > lipo ~ > ~ > > > vtx > ~ > lollipop > lolipop battery > ~ > ~ > ~ > mkF > > BEC > BEC ~ > LED > ~ > driver > ~ > ~ > > AAA > AA > M mm > > mW > V > A deans > t-plug tplug > t-plug
Buchstaben an Zahlen kleben
Manchmal sind Zahlen Teil des Namens (z. B. LCD5208D), aber häufiger ein Merkmal (100 mAh, 10 x 15 x 4 mm). Trennen Sie alle Zahlen von Buchstaben und Index.
Dies wird mehrere Probleme lösen:
- Jemand wird nach "Lager 10x15x4" suchen, jemand nach "Lager 15x10x4". Indizierte Zahlen führen zur korrekten Ausgabe.
- Maßeinheiten können durch ein Leerzeichen von der Zahl "1,75 mm", "1,75 mm" getrennt sein oder nicht.
- Für Titel ist dies ebenfalls nützlich. Die korrekte Ausgabe erfolgt über die drei Aufnahmeoptionen LCD-5208, LCD 5208 und LCD5208
Bevor Sie einen regulären Ausdruck schreiben, um Zahlen zu trennen, müssen Sie die Trennzeichen vereinheitlichen. Es ist wichtig zu beachten, dass reguläre Ausdrücke alle und nacheinander ausgeführt werden.
Wir entfernen das x, er und den Stern in Größen wie 10x4x4 M3x10:
regexp_filter = (\d+)[x\x{0445}\*] => \1 x
Lass die Schwänze fallen:
regexp_filter = (\d*\.?\d+)(\D+) => \1 \2
Und die Köpfe:
regexp_filter = (\D+)(\d*\.?\d+) => \1 \2
Wir verwerfen "mm", da diese im Namen des Produkts oft nicht angegeben sind.
Erstellen Sie eine stop.txt-Datei und schreiben Sie sie in Stoppwörter.
Inhalt:
mm
Nun ein wenig zu PHP
Sphinxapi wird früher oder später beraubt. Wir werden Sphinxql verwenden. Stellen Sie dazu eine Verbindung zur Datenbank her. In meinem Fall ist Sphinx über Hosting verbunden, es sieht so aus:
$opt = array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => TRUE, ); $dsn = 'mysql:host=127.0.0.1;port=9306;'; $this->pdo = new PDO($dsn, DB_USER, DB_PASS, $opt);
Die gesamte Kommunikation mit Spinxql erfolgt mit einem SELECT, das gefilterten Abfragetext überträgt
$stmt = $this->pdo->prepare("SELECT `id`, WEIGHT() as `w`, in_stock>0 AS stock FROM `items` WHERE MATCH ('".$search."') ORDER BY clearance ASC, stock DESC, w DESC LIMIT ".$limit." OPTION field_weights=(name=10, art=3, cat_names=3, model_names=3)");
SphinxQL versteht die Ausdrücke im Sortierabschnitt ORDER BY nicht, daher mussten WEIGHT () und in_stock> 0 in Felder eingefügt werden. Das Standardlimit beträgt übrigens nur 20.
Beim Sortieren werden zuerst Artikel auf Lager erstellt, dann vorübergehend nicht vorhanden und dann archiviert. Und alle diese drei Gruppen werden nach Relevanz (Gewicht) sortiert.
Durch field_weights legen wir fest, welche Felder mehr Gewicht haben.
Durch Abschluss der Anfrage erhalten wir ein sortiertes ID-Array. Leider verstößt die Datenauswahl über WHERE id IN () gegen diese Sortierung. Müssen Sie Ihre Anfrage für jede ID bilden.
In der Debugging-Phase hilft die SHOW META- Abfrage unmittelbar nach der SELECT-Abfrage sehr. Speziell zum Überprüfen von Wörterbuchwortformen und Filtern für reguläre Ausdrücke. Sie können die Liste der Schlüsselwörter anzeigen, in die die Abfrage erweitert wurde.
Komplizierung von sql_query
Wir verkaufen Ersatzteile. Ich habe beschlossen, den Namen der Produktkategorie und den Namen des Modells hinzuzufügen, für das das Ersatzteil in den Index aufgenommen werden soll. Jedes Produkt kann jedoch gleichzeitig an mehrere Kategorien gebunden werden und für mehrere Modelle geeignet sein. Und ich habe die GROUP_CONCAT- Funktion entdeckt, mit der Sie Daten abrufen können, indem Sie sie zu einer Zeichenfolge gruppieren. Das Feld category.name enthält beispielsweise alle Kategorien der ausgewählten items_zip.id, die durch Leerzeichen getrennt sind.
SELECT items_zip.id, `art`, items_zip.`name`, `clearance`, `in_stock`, GROUP_CONCAT(DISTINCT categories.name SEPARATOR ' ') AS cat_names, GROUP_CONCAT(DISTINCT items.family SEPARATOR ' ') AS model_names FROM items_zip LEFT JOIN items_cat ON items_cat.item_id=items_zip.id LEFT JOIN categories ON categories.id=items_cat.cat_id LEFT JOIN zip_comp ON zip_comp.zip_id=items_zip.id LEFT JOIN items ON zip_comp.model_id=items.id WHERE items_zip.show_flag=1 GROUP BY items_zip.id