Eine Fuzzy-Suchbibliothek für PHP
Dies ist eine PHP-Portierung des großartigen Fuse.js-Projekts und zielt darauf ab, wo immer möglich vollständige API-Kompatibilität bereitzustellen.
Schauen Sie sich die Demo und Beispiele an, um einen guten Eindruck davon zu bekommen, wozu diese Bibliothek in der Lage ist.
Neueste kompatible Fuse.js-Version: 7.0.0
Inhaltsverzeichnis:
Dieses Paket ist über Composer erhältlich. Um es Ihrem Projekt hinzuzufügen, führen Sie einfach Folgendes aus:
composer require loilo/fuse
Beachten Sie, dass für die Verwendung von Fuse mindestens PHP 7.4 erforderlich ist.
Hier ist ein einfaches Anwendungsbeispiel:
<?php
require_once ' vendor/autoload.php ' ;
$ list = [
[
' title ' => " Old Man's War " ,
' author ' => ' John Scalzi ' ,
],
[
' title ' => ' The Lock Artist ' ,
' author ' => ' Steve Hamilton ' ,
],
[
' title ' => ' HTML5 ' ,
' author ' => ' Remy Sharp ' ,
],
[
' title ' => ' Right Ho Jeeves ' ,
' author ' => ' P.D Woodhouse ' ,
],
];
$ options = [
' keys ' => [ ' title ' , ' author ' ],
];
$ fuse = new Fuse Fuse ( $ list , $ options );
$ fuse -> search ( ' hamil ' );
Dies führt zu den folgenden Ergebnissen (wobei sich das item
jedes Ergebnisses auf den übereinstimmenden Eintrag selbst bezieht und refIndex
die Position des Elements in der ursprünglichen $list
angibt):
[
[
' item ' => [
' title ' => ' The Lock Artist ' ,
' author ' => ' Steve Hamilton ' ,
],
' refIndex ' => 1 ,
],
[
' item ' => [
' title ' => ' HTML5 ' ,
' author ' => ' Remy Sharp ' ,
],
' refIndex ' => 2 ,
],
];
Fuse bietet viele Optionen, um Ihre Suche zu verfeinern:
isCaseSensitive
bool
false
Gibt an, ob bei Vergleichen zwischen Groß- und Kleinschreibung unterschieden werden soll.
includeScore
bool
false
Ob die Punktzahl in den Ergebnissatz einbezogen werden soll. Ein Wert von 0
weist auf eine perfekte Übereinstimmung hin, während ein Wert von 1
auf eine vollständige Nichtübereinstimmung hinweist.
includeMatches
bool
false
Ob die Übereinstimmungen in den Ergebnissatz aufgenommen werden sollen. Bei true
enthält jeder Datensatz im Ergebnissatz die Indizes der übereinstimmenden Zeichen. Diese können somit zu Hervorhebungszwecken genutzt werden.
minMatchCharLength
int
1
Es werden nur Übereinstimmungen zurückgegeben, deren Länge diesen Wert überschreitet. (Wenn Sie beispielsweise einzelne Zeichenübereinstimmungen im Ergebnis ignorieren möchten, setzen Sie den Wert auf 2
).
shouldSort
bool
true
Ob die Ergebnisliste nach Punktzahl sortiert werden soll.
findAllMatches
bool
false
Bei „true“ wird die Matching-Funktion bis zum Ende eines Suchmusters fortgesetzt, auch wenn in der Zeichenfolge bereits eine perfekte Übereinstimmung gefunden wurde.
keys
array
[]
Liste der Schlüssel, die durchsucht werden. Dies unterstützt verschachtelte Pfade, gewichtete Suche und die Suche in Arrays von Zeichenfolgen und Objekten.
location
int
0
Bestimmt ungefähr, wo im Text das erwartete Muster zu finden ist.
threshold
float
0.6
An welchem Punkt gibt der Match-Algorithmus auf? Ein Schwellenwert von 0.0
erfordert eine perfekte Übereinstimmung (sowohl der Buchstaben als auch des Ortes), ein Schwellenwert von 1.0
würde mit allem übereinstimmen.
distance
int
100
Bestimmt, wie nah die Übereinstimmung am Fuzzy-Standort sein muss (angegeben durch location
). Eine exakte Buchstabenübereinstimmung, bei der es sich um distance
von der Fuzzy-Position handelt, würde als völlige Nichtübereinstimmung gewertet. Bei einem distance
von 0
muss die Übereinstimmung genau an der angegebenen location
erfolgen. Eine Entfernung von 1000
würde erfordern, dass eine perfekte Übereinstimmung innerhalb von 800
Zeichen vom zu findenden location
liegt, wobei ein threshold
von 0.8
verwendet wird.
ignoreLocation
bool
false
Bei true
ignoriert die Suche location
und distance
, sodass es keine Rolle spielt, wo in der Zeichenfolge das Muster erscheint.
Tipp: Die Standardoptionen durchsuchen nur die ersten 60 Zeichen. Dies sollte ausreichen, wenn vernünftigerweise davon ausgegangen werden kann, dass die Übereinstimmung innerhalb dieses Bereichs liegt. Um dieses Verhalten zu ändern, legen Sie die entsprechende Kombination aus
location
,threshold
unddistance
(oderignoreLocation
) fest.Um besser zu verstehen, wie diese Optionen zusammenarbeiten, lesen Sie die Scoring-Theorie von Fuse.js.
useExtendedSearch
bool
false
Wenn true
, ermöglicht es die Verwendung von Unix-ähnlichen Suchbefehlen. Siehe Beispiel.
getFn
callable
Die Funktion, die zum Abrufen des Werts eines Objekts am angegebenen Pfad verwendet werden soll. Standardmäßig werden auch verschachtelte Pfade durchsucht.
sortFn
callable
Die Funktion, die zum Sortieren aller Ergebnisse verwendet werden soll. Standardmäßig wird nach aufsteigendem Relevanzwert und aufsteigendem Index sortiert.
ignoreFieldNorm
bool
false
Bei true
ignoriert die Berechnung des Relevanzfaktors (der zum Sortieren verwendet wird) die Feldlängennorm.
Tipp: Es macht nur dann Sinn,
ignoreFieldNorm
auftrue
zu setzen, wenn es nicht darauf ankommt, wie viele Begriffe vorhanden sind, sondern nur darauf, dass der Abfragebegriff existiert.
fieldNormWeight
float
1
Bestimmt, wie stark sich die Feldlängennorm auf die Bewertung auswirkt. Ein Wert von 0
entspricht dem Ignorieren der Feldlängennorm. Ein Wert von 0.5
verringert den Effekt der Feldlängennorm erheblich, während ein Wert von 2.0
ihn erheblich verstärkt.
Sie können über die config
auf die Standardwerte aller oben genannten Optionen zugreifen und diese bearbeiten:
// Get an associative array of all options listed above
Fuse :: config ();
// Merge associative array of options into default config
Fuse :: config ([ ' shouldSort ' => false ]);
// Get single default option
Fuse :: config ( ' shouldSort ' );
// Set single default option
Fuse :: config ( ' shouldSort ' , false );
Die folgenden Methoden sind auf jeder FuseFuse
-Instanz verfügbar:
search
Durchsucht die gesamte Dokumentensammlung und gibt eine Liste mit Suchergebnissen zurück.
public function search( mixed $ pattern , ? array $ options ): array
Das $pattern
kann eines der folgenden sein:
Die $options
:
limit
(Typ: int
): Gibt die maximale Anzahl zurückgegebener Suchergebnisse an.setCollection
Die gesamte Dokumentensammlung festlegen/ersetzen. Wenn kein Index angegeben ist, wird einer generiert.
public function setCollection( array $ docs , ? Fuse Core FuseIndex $ index ): void
Beispiel:
$ fruits = [ ' apple ' , ' orange ' ];
$ fuse = new Fuse ( $ fruits );
$ fuse -> setCollection ([ ' banana ' , ' pear ' ]);
add
Fügt der Sammlung ein Dokument hinzu und aktualisiert den Index entsprechend.
public function add( mixed $ doc ): void
Beispiel:
$ fruits = [ ' apple ' , ' orange ' ];
$ fuse = new Fuse ( $ fruits );
$ fuse -> add ( ' banana ' );
sizeof ( $ fruits ); // => 3
remove
Entfernt alle Dokumente aus der Liste, für die das Prädikat die Wahrheit zurückgibt, und gibt ein Array der entfernten Dokumente zurück. Das Prädikat wird mit zwei Argumenten aufgerufen: ($doc, $index)
.
public function remove(? callable $ predicate ): array
Beispiel:
$ fruits = [ ' apple ' , ' orange ' , ' banana ' , ' pear ' ];
$ fuse = new Fuse ( $ fruits );
$ results = $ fuse -> remove (fn( $ doc ) => $ doc === ' banana ' || $ doc === ' pear ' );
sizeof ( $ fuse -> getCollection ()); // => 2
$ results ; // => ['banana', 'pear']
removeAt
Entfernt das Dokument am angegebenen Index.
public function removeAt( int $ index ): void
Beispiel:
$ fruits = [ ' apple ' , ' orange ' , ' banana ' , ' pear ' ];
$ fuse = new Fuse ( $ fruits );
$ fuse -> removeAt ( 1 );
$ fuse -> getCollection (); // => ['apple', 'banana', 'pear']
getIndex
Gibt den generierten Fuse-Index zurück.
public function getIndex(): Fuse Core FuseIndex
Beispiel:
$ fruits = [ ' apple ' , ' orange ' , ' banana ' , ' pear ' ];
$ fuse = new Fuse ( $ fruits );
$ fuse -> getIndex ()-> size (); // => 4
Die folgenden Methoden sind auf jeder FuseFuse
-Instanz verfügbar:
Fuse::createIndex
Generieren Sie den Index vorab aus der Liste und übergeben Sie ihn direkt an die Fuse-Instanz. Wenn die Liste (erheblich) groß ist, beschleunigt es die Instanziierung.
public static function createIndex( array $ keys , array $ docs , array $ options = []): Fuse Core FuseIndex
Beispiel:
$ list = [ ... ]; // See the example from the 'Usage' section
$ options = [ ' keys ' => [ ' title ' , ' author.firstName ' ] ];
// Create the Fuse index
$ myIndex = Fuse :: createIndex ( $ options [ ' keys ' ], $ list );
// Initialize Fuse with the index
$ fuse = new Fuse ( $ list , $ options , $ myIndex );
Fuse::parseIndex
Analysiert einen JSON-serialisierten Fuse-Index.
public static function parseIndex( array $ data , array $ options = []): Fuse Core FuseIndex
Beispiel:
// (1) When the data is collected
$ list = [ ... ]; // See the example from the 'Usage' section
$ options = [ ' keys ' => [ ' title ' , ' author.firstName ' ] ];
// Create the Fuse index
$ myIndex = Fuse :: createIndex ( $ options [ ' keys ' ], $ list );
// Serialize and save it
file_put_contents ( ' fuse-index.json ' , json_encode ( $ myIndex ));
// (2) When the search is needed
// Load and deserialize index to an array
$ fuseIndex = json_decode ( file_get_contents ( ' fuse-index.json ' ), true );
$ myIndex = Fuse :: parseIndex ( $ fuseIndex );
// Initialize Fuse with the index
$ fuse = new Fuse ( $ list , $ options , $ myIndex );
Fuse.js | PHP-Sicherung | |
---|---|---|
Holen Sie sich die Fuse-Version | Fuse.version | – |
Greifen Sie auf die globale Konfiguration zu | Fuse.config Eigenschaft | Fuse::config Methode |
Listenänderung | Die Verwendung von fuse.add() usw. ändert die ursprüngliche Liste, die an den new Fuse Konstruktor übergeben wird. | In PHP sind Arrays ein primitiver Datentyp, was bedeutet, dass Ihre ursprüngliche Liste niemals von Fuse geändert wird. Um die aktuelle Liste nach dem Hinzufügen/Entfernen von Elementen zu erhalten, kann die Methode $fuse->getCollection() verwendet werden. |
Bitte beachten Sie, dass ich Funktionsparität mit Fuse.js anstrebe und daher weder Funktionen noch Korrekturen zur Suchlogik hinzufügen werde, die nicht in Fuse.js selbst widergespiegelt werden.
Wenn Sie Probleme mit Suchergebnissen haben, die nicht offensichtlich auf Fehler in dieser PHP-Portierung zurückzuführen sind, und Sie zufällig JavaScript beherrschen, überprüfen Sie bitte in der Online-Demo von Fuse.js, ob Ihr Anwendungsfall korrekt funktioniert, da es sich um die kanonische Fuse-Implementierung handelt. Wenn das Problem auch dort auftritt, öffnen Sie bitte ein Problem in ihrem Repo.
Um mit der Entwicklung auf Fuse zu beginnen, benötigen Sie Git, PHP (≥ 7.4) und Composer.
Da Code mit Prettier formatiert wird, wird außerdem empfohlen, Node.js/npm installiert zu haben und einen Editor zu verwenden, der die Prettier-Formatierung unterstützt.
Klonen Sie das Repository und cd
hinein:
git clone https://github.com/loilo/fuse.git
cd fuse
Composer-Abhängigkeiten installieren:
composer install
Installieren Sie NPM-Abhängigkeiten (optional, aber empfohlen). Dies ist nur für die Codeformatierung erforderlich, da npm-Abhängigkeiten die von diesem Projekt verwendeten Prettier-Plugins umfassen.
npm ci
Für dieses Projekt gibt es verschiedene Arten von Codeprüfungen. All dies wird ausgeführt, wenn eine Pull-Anfrage gesendet wird, kann aber auch lokal ausgeführt werden:
Befehl | Zweck | Beschreibung |
---|---|---|
vendor/bin/phpcs | Überprüfen Sie den Codestil | Führen Sie PHP_CodeSniffer aus, um zu überprüfen, ob der Fuse-Quellcode dem PSR-12-Codierungsstil entspricht. |
vendor/bin/psalm | statische Analyse | Führen Sie Psalm gegen die Codebasis aus, um typbezogene Fehler und unsichere Codierungsmuster zu vermeiden. |
vendor/bin/phpunit | Überprüfen Sie die Programmlogik | Führen Sie alle PHPUnit-Tests aus dem test aus. |
Bevor Sie eine Pull-Anfrage senden, fügen Sie bitte relevante Tests zum test
hinzu.