Elasticsearch의 쿼리의 힘을 가진 Laravel Scout의 Elasticsearch 드라이버.
작곡가를 통해
composer require hilsonxhero/elasticvision인덱스를 정의하려면 구성 파일이 필요합니다.
php artisan vendor:publish --tag=elasticvision-config 또한 Laravel Scout의 설치 지침을 따르고 Laravel Scout 구성에서는 드라이버를 elastic 으로 설정하는 것을 잊지 마십시오.
ElasticVision Config 파일에서 인덱스에 대한 매핑을 정의 할 수 있습니다.
return [
' indexes ' => [
App Models Product ::class,
],
];php artisan scout:index productsphp artisan scout:import " AppModelsProduct " 마지막 경우 Explored 인터페이스를 구현하고 mappableAs() 함수로 매핑을 덮어 쓸 수 있습니다.
본질적으로 이것은 모델에 모두 함께 갖는 것을 좋아하든 구성 파일에서 별도로 갖고 있음을 의미합니다.
제공된 필드에 정확한 용어가 포함 된 문서를 반환합니다.
쿼리라는 용어를 사용하여 가격, 제품 ID 또는 사용자 이름과 같은 정확한 값을 기반으로 문서를 찾을 수 있습니다.
use App Models Post ;
$ posts = Post :: search ( ' lorem ' )
-> filter ( new Term ( ' published ' , true ))
-> get ();제공된 필드에 하나 이상의 정확한 용어가 포함 된 문서를 반환합니다.
쿼리 용어는 여러 값을 검색 할 수있는 경우를 제외하고 쿼리 용어와 동일합니다. 문서는 용어 중 하나 이상이 포함 된 경우 문서가 일치합니다. 하나 이상의 일치하는 용어가 포함 된 문서를 검색합니다.
use App Models Post ;
$ posts = Post :: search ( ' lorem ' )
-> should ( new Terms ( ' tags ' , [ ' featured ' ], 2 ))
-> get (); field
(선택 사항, 개체) 필드 검색하려는 필드.
boost
(선택적, 플로트) 부동 소수점 번호는 쿼리의 관련성 점수를 줄이거 나 늘리는 데 사용됩니다. 기본값은 1.0입니다.
기본적으로 Elasticsearch에 따르면 검색 결과는 점수별로 정렬됩니다. Laravel Scout의 Default orderBy() 함수를 사용하여 들어가서 분류에 영향을 미치려면 정렬에 영향을 줄 수 있습니다.
use App Models Post ;
$ results = Post :: search ( ' Self-steering ' )
-> orderBy ( ' published_at ' , ' desc ' )
-> get ();제공된 범위 내에 용어가 포함 된 문서를 반환합니다.
use App Models User ;
$ results = User :: search ( ' fugiat ' )-> must ( new Range ( ' age ' ,[ ' gte ' => 18 , ' lte ' => 35 ]))-> get ();정규 표현식과 일치하는 용어가 포함 된 문서를 반환합니다.
정규 표현식은 연산자라고하는 자리 표시 자 문자를 사용하여 데이터의 패턴을 일치시키는 방법입니다. REGEXP 쿼리에서 지원하는 연산자 목록은 일반 표현식 구문을 참조하십시오.
use App Models User ;
$ results = User :: search ( ' fugiat ' )-> must ( new RegExp ( ' username ' , ' k.*y ' , ' ALL ' , false ))-> get (); field
(선택 사항, 개체) 필드 검색하려는 필드.
value
(필수, 문자열) 제공된 <field> 에서 찾으려는 용어에 대한 정기 표현. 지원되는 연산자 목록은 정규식 구문을 참조하십시오.
flags
(선택 사항, String)은 정규 표현식에 대한 선택적 연산자가 가능합니다. 유효한 값과 자세한 정보는 정규식 구문을 참조하십시오.
case_insensitive
(선택 사항, 부울)는 정규 표현식 값을 인덱스 된 필드 값과 true로 설정할 때 사례의 무감각 일치를 허용합니다. 기본값은 거짓이므로 일치하는 경우의 민감도는 기본 필드의 매핑에 따라 다릅니다.
boost
(선택적, 플로트) 부동 소수점 번호는 쿼리의 관련성 점수를 줄이거 나 늘리는 데 사용됩니다. 기본값은 1.0입니다.
와일드 카드 패턴과 일치하는 용어가 포함 된 문서를 반환합니다.
와일드 카드 운영자는 하나 이상의 문자와 일치하는 자리 표시 자입니다. 예를 들어, * 와일드 카드 연산자는 0 개 이상의 문자와 일치합니다. 와일드 카드 연산자와 다른 문자를 결합하여 와일드 카드 패턴을 만들 수 있습니다.
use App Models User ;
$ users = User :: search ()
-> should ( new Wildcard ( ' username ' , ' ki*y ' ))
-> get ();제공된 텍스트, 번호, 날짜 또는 부울 값과 일치하는 문서를 반환합니다. 제공된 텍스트는 일치하기 전에 분석됩니다.
일치 쿼리는 퍼지 매칭 옵션을 포함하여 전체 텍스트 검색을 수행하기위한 표준 쿼리입니다.
use App Models Article ;
$ articles = Article :: search ()
-> must ( new Matching ( ' title ' , ' ipsum ' ))
-> get ();제공된 텍스트의 단어가 포함 된 문서를 제공 한 것과 동일한 순서로 반환합니다. 제공된 텍스트의 마지막 용어는 해당 용어로 시작하는 단어와 일치하는 접두사로 취급됩니다.
use App Models User ;
$ users = User :: search ()
-> should ( new MatchPhrasePrefix ( ' message ' , ' quick brown f ' ))
-> get (); match_phrase query는 텍스트를 분석하고 분석 된 텍스트에서 phrase 쿼리를 만듭니다. 예를 들어:
use App Models User ;
$ users = User :: search ()
-> should ( new MatchPhrase ( ' message ' , ' this is a test ' ))
-> get ();중첩 된 필드를 검색하기 위해 다른 쿼리를 랩핑합니다.
nested 쿼리는 마치 별도의 문서로 인덱싱 된 것처럼 중첩 된 필드 객체를 검색합니다. 객체가 검색과 일치하면 nested 쿼리가 루트 상위 문서를 반환합니다.
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 );문구 쿼리는 항을 구성 가능한 슬로프 (기본값 0)까지 순서대로 일치시킵니다. 전환 된 용어의 슬로프는 2입니다.
분석기는 텍스트에서 분석 프로세스를 수행 할 분석기를 제어하도록 설정할 수 있습니다. 필드 명시 적 맵핑 정의 또는 기본 검색 분석기로 기본값이 표시됩니다.
인덱스 매핑을 통해 수행 할 대부분의 구성. 그러나 예를 들어 분석기 또는 토큰 화제와 같은 고급 Elasticsearch 설정을 정의하려면 색인 설정을 사용해야합니다.
색인 설정을 변경할 때마다 인덱스를 재현해야합니다.
인덱스 설정 사용을 시작하려면 분석기를 설정하기 위해 indexSettings 함수를 사용하여 포스트 모델을 확장합니다.
<?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 ' ],
],
],
],
];
}
}텍스트 분석은 인덱스 설정의 일부로 설정됩니다.
다음 예제는 동의어 분석기를 만듭니다. 최종 결과는 'vue'를 검색 할 때 'React'에 대한 결과를 얻는 것입니다. 동의어가 모든 케이스와 일치하는지 확인하기 위해 lowercase 필터도 실행됩니다.
<?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 ();
}
}집계는 검색 쿼리의 일부이며 데이터를 요약 할 수 있습니다. 공식 문서의 Elasticsearch에서 집계에 대한 자세한 내용을 읽을 수 있습니다. 현재 모든 집계 유형이 구축되는 것은 아니지만 누락 된 유형을 만들 수 있어야합니다 (패키지에 추가 된 것은 매우 환영합니다).
집계를 추가하면 검색 쿼리가 더욱 발전 할 수 있습니다. 다음은 데모 응용 프로그램의 예입니다.
$ search = Cartographer :: search ();
$ search -> aggregation ( ' places ' , new TermsAggregation ( ' place ' ));
$ results = $ search -> raw ();
$ aggregations = $ results -> aggregations ();이렇게하면 Elasticsearch Index에 모든 장소가 몇 번 존재하는지에 대한 다양한 메트릭이 반환됩니다.
동의어 필터와 분석기를 만드는 것은 매우 쉽지만 Elasticsearch에서 실행하는 데 '비싸다'는 사실에 유의하십시오. 동의어로 전환하기 전에 와일드 카드 또는 퍼지 쿼리를 사용할 수 있는지 확인하십시오.
Laravel Scout의 문서에 따르면 "조항이 현재 지원되지 않는"더 발전된 "것으로 나타났습니다. 표준 퍼지 용어 검색 외에 간단한 ID에 대한 간단한 확인 만 가능합니다.
$ categories = Category :: search ( ' lorem ipsum ' )-> filter ( new MatchPhrase ( ' status ' , ' enable ' ))-> take ( 15 )-> get ();ElasticVision은 쿼리 빌더를 사용하여 가능성을 확장하여 더 복잡한 쿼리를 작성합니다.
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
);
}
}
예를 들어, 모든 게시물을 얻으려면 다음과 같습니다.
이 검색 쿼리를 실행할 수 있습니다.
$ 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 ;때로는 특정 결과가 왜 반환되지 않았는지 궁금 할 수도 있습니다.
다음은 복잡한 쿼리가 아니지만 ElasticVision 데모 앱의 예입니다.
class SearchController
{
public function __invoke ( SearchFormRequest $ request )
{
$ people = Cartographer :: search ( $ request -> get ( ' keywords ' ))-> get ();
return view ( ' search ' , [
' people ' => $ people ,
]);
}
} 이 검색 쿼리를 디버그하려면 Laravel Scout의 탄성 엔진에서 정적 debug 방법을 호출 할 수 있습니다.
use Hilsonxhero ElasticVision Infrastructure Scout ElasticEngine ;
$ debug = ElasticEngine :: debug ();이 메소드가 반환하는 디버그 클래스는 마지막으로 실행 된 쿼리를 배열 또는 JSON으로 제공 할 수 있습니다. elasticsearch의 직접 쿼리로 JSON을 복사 할 수 있어야합니다.
$ lastQueryAsArray = ElasticEngine :: debug ()-> array ();
$ lastQueryAsJson = ElasticEngine :: debug ()-> json ();Laravel Scout 가져 오기 명령을 사용하여 지수를 작성하고 업데이트하십시오.
php artisan scout:import <model>
예를 들어, 모델이 "app models post"인 경우 명령은 다음과 같습니다.
php artisan scout:import "AppModelsPost"
인덱스를 다시 만들려면 먼저 삭제 된 상태를 확인한 다음 작성하십시오. 스카우트 수입으로 후속 조치를 취하여 색인을 리필하십시오.
별명 인덱스를 사용하는 경우 scout:import
php artisan elastic:update <index?>
인덱스를 지정하거나 생략하도록 선택할 수 있으며 명령은 모든 인덱스를 업데이트합니다. 예를 들어, 모델이 "app model post"이고 색인이 "게시물"인 경우 :
php artisan elastic:update posts
php artisan scout:delete-index <model>
Laravel Scount Delete-Index 명령을 사용하여 지수를 삭제하십시오.
config/elasticvision.php 에서 먼저 인덱스를 구성하고 스카우트 명령을 실행했는지 확인하십시오.