Elasticsearch -Treiber für Laravel Scout mit der Kraft der Fragen von Elasticsearch.
Über Komponist
composer require hilsonxhero/elasticvisionSie benötigen die Konfigurationsdatei, um Ihre Indizes zu definieren:
php artisan vendor:publish --tag=elasticvision-config Vergessen Sie auch nicht, die Installationsanweisungen für Laravel Scout zu befolgen, und stellen Sie den Treiber in Ihrer Laravel Scout -Konfiguration auf elastic .
Sie können entweder die Zuordnung für Ihren Index in der Elasticvision -Konfigurationsdatei definieren:
return [
' indexes ' => [
App Models Product ::class,
],
];php artisan scout:index productsphp artisan scout:import " AppModelsProduct " Im letzten Fall können Sie die Explored Schnittstelle implementieren und die Zuordnung mit der Funktion mappableAs() überschreiben.
Dies bedeutet im Wesentlichen, dass es an Ihnen liegt, ob Sie gerne alles zusammen im Modell oder separat in der Konfigurationsdatei haben.
Gibt Dokumente zurück, die einen genauen Begriff in einem bereitgestellten Feld enthalten.
Sie können die Begriffsabfrage verwenden, um Dokumente zu finden, die auf einem genauen Wert wie einem Preis, einer Produkt -ID oder einem Benutzernamen basieren.
use App Models Post ;
$ posts = Post :: search ( ' lorem ' )
-> filter ( new Term ( ' published ' , true ))
-> get ();Gibt Dokumente zurück, die einen oder mehrere exakte Begriffe in einem bereitgestellten Feld enthalten.
Die Abfrage der Begriffe entspricht der Begriffsabfrage, außer dass Sie nach mehreren Werten suchen können. Ein Dokument stimmt überein, wenn es mindestens einen der Begriffe enthält. Suche nach Dokumenten, die mehr als einen übereinstimmenden Begriff enthalten.
use App Models Post ;
$ posts = Post :: search ( ' lorem ' )
-> should ( new Terms ( ' tags ' , [ ' featured ' ], 2 ))
-> get (); field
(Optional, Objekt) Feld Sie suchen möchten.
boost
(Optional, float) schwimmende Punktzahl, die zur Verringerung oder Erhöhung der Relevanzwerte einer Abfrage verwendet wird. Standardeinstellung auf 1.0.
Standardmäßig werden Ihre Suchergebnisse nach Elasticsearch nach ihrer Punktzahl sortiert. Wenn Sie einsteigen und die Sortierung beeinflussen möchten, können Sie dies mit der Standard orderBy() -Funktion von Laravel Scout tun.
use App Models Post ;
$ results = Post :: search ( ' Self-steering ' )
-> orderBy ( ' published_at ' , ' desc ' )
-> get ();Gibt Dokumente zurück, die Begriffe innerhalb eines bereitgestellten Bereichs enthalten.
use App Models User ;
$ results = User :: search ( ' fugiat ' )-> must ( new Range ( ' age ' ,[ ' gte ' => 18 , ' lte ' => 35 ]))-> get ();Gibt Dokumente zurück, die Begriffe enthalten, die einem regulären Ausdruck entsprechen.
Ein regulärer Ausdruck ist eine Möglichkeit, Muster in Daten mit den als Operatoren bezeichneten Platzhalterzeichen zu entsprechen. Eine Liste von Betreibern, die von der Regexp -Abfrage unterstützt werden, siehe regelmäßige Expressionssyntax.
use App Models User ;
$ results = User :: search ( ' fugiat ' )-> must ( new RegExp ( ' username ' , ' k.*y ' , ' ALL ' , false ))-> get (); field
(Optional, Objekt) Feld Sie suchen möchten.
value
(Erforderlich, Zeichenfolge) Regelmäßiger Ausdruck für Begriffe, die Sie in der bereitgestellten <field> finden möchten. Eine Liste unterstützter Operatoren finden Sie in der regulären Expressionssyntax.
flags
(Optional, Zeichenfolge) ermöglicht optionale Bediener für den regulären Ausdruck. Für gültige Werte und weitere Informationen siehe reguläre Expressionssyntax.
case_insensitive
(Optional, boolean) Ermöglicht die unempfindliche Übereinstimmung des regulären Expressionswerts mit den indizierten Feldwerten, wenn sie auf TRUE gesetzt sind. Standard ist falsch, was bedeutet, dass die Fallempfindlichkeit der Übereinstimmung von der Zuordnung des zugrunde liegenden Feldes abhängt.
boost
(Optional, float) schwimmende Punktzahl, die zur Verringerung oder Erhöhung der Relevanzwerte einer Abfrage verwendet wird. Standardeinstellung auf 1.0.
Gibt Dokumente zurück, die Begriffe enthalten, die ein Wildcard -Muster entsprechen.
Ein Platzhalterbetreiber ist ein Platzhalter, der einem oder mehreren Zeichen entspricht. Zum Beispiel entspricht der * Wildcard -Operator mit Null oder mehr Zeichen. Sie können Wildcard -Operatoren mit anderen Charakteren kombinieren, um ein Wildcard -Muster zu erstellen.
use App Models User ;
$ users = User :: search ()
-> should ( new Wildcard ( ' username ' , ' ki*y ' ))
-> get ();Gibt Dokumente zurück, die einem bereitgestellten Text, Nummer, Datum oder Booleschen Wert entsprechen. Der bereitgestellte Text wird vor dem Übereinstimmung analysiert.
Die Match-Abfrage ist die Standardabfrage für die Durchführung einer Volltext-Suche, einschließlich Optionen für Fuzzy-Matching.
use App Models Article ;
$ articles = Article :: search ()
-> must ( new Matching ( ' title ' , ' ipsum ' ))
-> get ();Gibt Dokumente zurück, die die Wörter eines bereitgestellten Textes enthalten, in derselben Reihenfolge wie angegeben. Der letzte Term des bereitgestellten Textes wird als Präfix behandelt und entspricht allen Wörtern, die mit diesem Begriff beginnen.
use App Models User ;
$ users = User :: search ()
-> should ( new MatchPhrasePrefix ( ' message ' , ' quick brown f ' ))
-> get (); Das match_phrase -Abfrage analysiert den Text und erstellt eine phrase -Abfrage aus dem analysierten Text heraus. Zum Beispiel:
use App Models User ;
$ users = User :: search ()
-> should ( new MatchPhrase ( ' message ' , ' this is a test ' ))
-> get ();Wickelt eine weitere Anfrage, um verschachtelte Felder zu durchsuchen.
Die nested Abfragen durchsuchen verschachtelte Feldobjekte, als wären sie als separate Dokumente indiziert. Wenn ein Objekt mit der Suche übereinstimmt, gibt die nested Abfrage das übergeordnete Stammdokument zurück.
use App Models Product ;
$ products = Product :: search ()
-> must ( new Nested ( ' category ' , new Term ( ' category.id ' , 2 )))
-> get (); use App Models Product ;
$ search = Product :: search ( " lorem " );
// $feature_ids = array([4 => [1,2], 5 => [1,2]])
foreach ( request ()-> feature_id as $ key => $ value ) {
$ query = new BoolQuery ();
$ query -> must ( new Term ( ' features.feature_id ' , $ key ));
$ query -> must ( new Terms ( ' features.feature_value_id ' , $ value ));
$ boolQuery -> add ( ' must ' , new Nested ( ' features ' , $ query ));
}
$ search -> newCompound ( $ boolQuery );
$ products = $ search -> paginate ( 15 );Eine Phrase -Abfrage stimmt den Begriffen bis zu einem konfigurierbaren Slop (der standardmäßig 0 in beliebiger Reihenfolge standardmäßig ist. Transponierte Begriffe haben eine Slop von 2.
Der Analysator kann so eingestellt werden, dass der Analysator den Analyseprozess im Text ausführt. Es wird standardmäßig das Feld explizite Zuordnungsdefinition oder den Standard -Suchanalysator für den Suchanalysator verwendet:
Der größte Teil der Konfiguration, die Sie durch die Zuordnung Ihres Index durchführen. Wenn Sie beispielsweise fortgeschrittenere Elasticsearch -Einstellungen wie Analysatoren oder Tokenisierer definieren möchten, müssen Sie dies mithilfe der Indexeinstellungen durchführen.
Beachten Sie, dass Sie jedes Mal, wenn Sie die Indexeinstellungen ändern, den Index neu erstellen müssen.
Um die Indexeinstellungen zu verwenden, erweitern wir das Postmodell mit einer indexSettings -Funktion, um einen Analysator festzulegen.
<?php
namespace App Models ;
use Illuminate Database Eloquent Factories HasFactory ;
use Illuminate Database Eloquent Model ;
use Hilsonxhero ElasticVision Application Explored ;
use Hilsonxhero ElasticVision Application IndexSettings ;
use Laravel Scout Searchable ;
class Post extends Model implements Explored , IndexSettings
{
use HasFactory ;
use Searchable ;
protected $ fillable = [ ' title ' , ' published ' ];
public function mappableAs (): array
{
return [
' id ' => ' keyword ' ,
' title ' => ' text ' ,
' published ' => ' boolean ' ,
' created_at ' => ' date ' ,
];
}
public function indexSettings (): array
{
return [
' analysis ' => [
' analyzer ' => [
' standard_lowercase ' => [
' type ' => ' custom ' ,
' tokenizer ' => ' standard ' ,
' filter ' => [ ' lowercase ' ],
],
],
],
];
}
}Die Textanalyse wird als Teil der Indexeinstellungen festgelegt.
Das folgende Beispiel erstellt einen Synonym -Analysator. Das Endergebnis wäre, dass Sie (auch) die Ergebnisse für "React" suchen, wenn Sie nach "Vue" suchen. Um sicherzustellen, dass die Synonyme mit allen Fällen übereinstimmen, wird auch der lowercase ausgeführt.
<?php
namespace App Models ;
use Illuminate Database Eloquent Factories HasFactory ;
use Illuminate Database Eloquent Model ;
use Hilsonxhero ElasticVision Application Explored ;
use Hilsonxhero ElasticVision Application IndexSettings ;
use Hilsonxhero ElasticVision Domain Analysis Analysis ;
use Hilsonxhero ElasticVision Domain Analysis Analyzer StandardAnalyzer ;
use Hilsonxhero ElasticVision Domain Analysis Filter SynonymFilter ;
use Laravel Scout Searchable ;
class Post extends Model implements Explored , IndexSettings
{
use HasFactory ;
use Searchable ;
protected $ fillable = [ ' title ' , ' published ' ];
public function mappableAs (): array
{
return [
' id ' => ' keyword ' ,
' title ' => [
' type ' => ' text ' ,
' analyzer ' => ' frameworks ' ,
],
' published ' => ' boolean ' ,
' created_at ' => ' date ' ,
];
}
public function indexSettings (): array
{
$ synonymFilter = new SynonymFilter ();
$ synonymFilter -> setSynonyms ([ ' vue => react ' ]);
$ synonymAnalyzer = new StandardAnalyzer ( ' frameworks ' );
$ synonymAnalyzer -> setFilters ([ ' lowercase ' , $ synonymFilter ]);
return ( new Analysis ())
-> addAnalyzer ( $ synonymAnalyzer )
-> addFilter ( $ synonymFilter )
-> build ();
}
}Aggregationen sind Teil Ihrer Suchabfrage und können Ihre Daten zusammenfassen. In der offiziellen Dokumentation können Sie mehr über Aggregationen in Elasticsearch lesen. In diesem Moment werden nicht alle Aggregationstypen eingebaut, aber das Erstellen der fehlenden sollte machbar sein (und diese Ergänzungen des Pakets sind sehr willkommen).
Durch das Hinzufügen von Aggregationen wird Ihre Suchabfrage fortgeschritten. Hier ist ein Beispiel aus der Demo -Anwendung:
$ search = Cartographer :: search ();
$ search -> aggregation ( ' places ' , new TermsAggregation ( ' place ' ));
$ results = $ search -> raw ();
$ aggregations = $ results -> aggregations ();Dadurch wird eine Reihe von Metriken zurückgegeben, wie oft jeder Ort im Elasticsearch -Index vorhanden ist.
Es ist sehr einfach, Synonymfilter und Analysatoren zu erstellen, aber seien Sie sich bewusst, dass sie für Elasticsearch "teuer" sind. Bevor Sie sich den Synonymen wenden, prüfen Sie, ob Sie Wildcards oder Fuzzy -Abfragen verwenden können.
In der Dokumentation von Laravel Scout heißt es, dass "fortgeschrittener" "Klauseln derzeit nicht unterstützt werden". Neben der serienmäßigen Fuzzy -Term -Suche ist nur eine einfache Überprüfung der ID möglich:
$ categories = Category :: search ( ' lorem ipsum ' )-> filter ( new MatchPhrase ( ' status ' , ' enable ' ))-> take ( 15 )-> get ();ElasticVision erweitert Ihre Möglichkeiten mit Abfragebägern, um komplexere Abfragen zu schreiben.
class Product extends Model implements Explored
{
public function mappableAs (): array
{
return [
' id ' => ' keyword ' ,
' title_fa ' => [
' type ' => ' text ' ,
' analyzer ' => ' my_analyzer ' ,
],
' title_en ' => [
' type ' => ' text ' ,
],
' status ' => [
' type ' => ' text ' ,
],
' category ' => ' nested ' ,
' features ' => ' nested ' ,
' variants ' => ' nested ' ,
' has_stock ' => ' boolean ' ,
];
}
public function toSearchableArray (): array
{
return [
' id ' => $ this -> id ,
' title ' => $ this -> title ,
' status ' => $ this -> status ,
' category ' => $ this -> category ,
' features ' => $ this -> features ,
' variants ' => ProductVariantResource :: collection ( $ this -> variants )-> toArray ( true ),
' has_stock ' => $ this -> has_stock ,
];
}
public function indexSettings (): array
{
return [
" analysis " => [
" analyzer " => [
" my_analyzer " => [
" type " => " custom " ,
" tokenizer " => " standard " ,
" filter " => [ " lowercase " , " my_filter " ]
]
],
" filter " => [
" my_filter " => [
" type " => " ngram " ,
" min_gram " => 2 ,
]
]
],
" index " => [
" max_ngram_diff " => 13
]
];
}
/**
* Get the name of the index associated with the model.
*
* @return string
*/
public function searchableAs ()
{
return ' products ' ;
}
public function category ()
{
return $ this -> belongsTo ( Category ::class);
}
public function variants ()
{
return $ this -> hasMany ( ProductVariant ::class);
}
public function features ()
{
return $ this -> hasMany ( ProductFeature ::class);
}
/**
* check inventory of product variations
*
* @return IlluminateDatabaseEloquentCastsAttribute
*/
protected function hasStock (): Attribute
{
return Attribute :: make (
get: fn ( $ value ) => $ this -> variants ()-> sum ( ' stock ' ) > 0 ? true : false
);
}
}
Zum Beispiel, um alle Beiträge zu erhalten, die:
Sie können diese Suchabfrage ausführen:
$ boolQuery = new BoolQuery ();
$ search = Product :: search ( " ipsum " )
-> field ( ' title ' )
-> field ( ' description ' )
-> filter ( new MatchPhrase ( ' status ' , ' enable ' ))
-> must ( new Nested ( ' category ' , new MatchPhrase ( ' category.id ' , 2 )));
if ( request ()-> filled ( ' available_stock ' )) {
$ search -> filter ( new Term ( ' has_stock ' , true ));
}
// request feature_ids value
// $feature_ids = array([4 => [1,2], 5 => [1,2]])
if ( request ()-> filled ( ' feature_ids ' )) {
foreach ( request ()-> feature_ids as $ key => $ value ) {
$ query = new BoolQuery ();
$ query -> must ( new MatchPhrase ( ' features.feature_id ' , $ key ));
$ query -> must ( new Terms ( ' features.feature_value_id ' , $ value ));
$ boolQuery -> add ( ' must ' , new Nested ( ' features ' , $ query ));
}
}
if ( request ()-> filled ( ' max_price ' ) && request ()-> filled ( ' min_price ' )) {
$ boolQuery -> add ( ' must ' , new Nested ( ' variants ' , new Range (
' variants.selling_price ' ,
[ ' gte ' => request ()-> min_price ]
)));
$ boolQuery -> add ( ' must ' , new Nested ( ' variants ' , new Range (
' variants.selling_price ' ,
[ ' lte ' => request ()-> max_price ]
)));
$ boolQuery -> add ( ' must_not ' , new Nested ( ' variants ' , new Range (
' variants.selling_price ' ,
[ ' lt ' => request ()-> min_price ]
)));
$ boolQuery -> add ( ' must_not ' , new Nested ( ' variants ' , new Range (
' variants.selling_price ' ,
[ ' gt ' => request ()-> max_price ]
)));
}
$ search -> newCompound ( $ boolQuery );
$ products = $ search -> paginate ( 15 );
return $ products ;Manchmal fragen Sie sich vielleicht, warum bestimmte Ergebnisse zurückgegeben werden oder werden.
Hier ist ein Beispiel aus der Elasticvision Demo -App, allerdings nicht mit einer komplexen Abfrage:
class SearchController
{
public function __invoke ( SearchFormRequest $ request )
{
$ people = Cartographer :: search ( $ request -> get ( ' keywords ' ))-> get ();
return view ( ' search ' , [
' people ' => $ people ,
]);
}
} Um diese Suchabfrage zu debuggen, können Sie die statische debug -Methode auf der Elastic Engine für Laravel Scout aufrufen:
use Hilsonxhero ElasticVision Infrastructure Scout ElasticEngine ;
$ debug = ElasticEngine :: debug ();Die Debug -Klasse, die diese Methode zurückgibt, kann Ihnen die zuletzt ausgeführte Abfrage als Array oder als JSON geben. Sie sollten in der Lage sein, den JSON als direkte Abfrage an Elasticsearch zu kopieren.
$ lastQueryAsArray = ElasticEngine :: debug ()-> array ();
$ lastQueryAsJson = ElasticEngine :: debug ()-> json ();Verwenden Sie den Befehl Laravel Scout -Import, um Indizes zu erstellen und zu aktualisieren.
php artisan scout:import <model>
Wenn Ihr Modell beispielsweise "App Models Post" ist, wäre der Befehl wie folgt:
php artisan scout:import "AppModelsPost"
Wenn Sie einen Index neu erstellen möchten, stellen Sie zunächst sicher, dass er gelöscht wird, und erstellen Sie ihn dann. Verfolgen Sie einen Scout -Import, um auch den Index nachzufüllen.
Wenn Sie aliased Indexes verwenden, sollten Sie diesen Befehl anstelle von scout:import
php artisan elastic:update <index?>
Sie können einen Index angeben oder ihn weglassen, und der Befehl aktualisiert alle Ihre Indizes. Wenn Ihr Modell beispielsweise "App Model Post" ist und der Index "Beiträge" ist:
php artisan elastic:update posts
php artisan scout:delete-index <model>
Verwenden Sie Laravel Scount Delete-Index-Befehl, um die Indizes zu löschen.
Stellen Sie sicher, dass Sie Ihre Indizes zuerst in config/elasticvision.php konfiguriert haben und die Scout -Befehle ausführen.