Plugin Pencarian untuk Episerver CMS and Commerce
Versi yang mendukung .NET 6+ tersedia. Hubungi Kristian Borg untuk detailnya.
Pertama -tama Anda perlu membuat indeks Anda. Buka halaman administrasi melalui mesin pencari menu tertanam -> administrasi dan status, lalu klik tombol Create indices .
Ini akan membuat satu indeks per bahasa di situs Anda. Jika Anda memiliki Addon Commerce diinstal, indeks tambahan untuk konten katalog juga akan dibuat.

Indeks terpisah akan dibuat untuk setiap bahasa aktif di situs Anda. Jika Anda menambahkan lebih banyak bahasa nanti, proses ini perlu diulang.
Anda dapat mengonfigurasi pengaturan Anda secara terprogram dengan singleton Epinova.ElasticSearch.Core.Conventions.Indexing . Hanya lakukan ini sekali per appdomain, biasanya dalam modul yang dapat diinisialisasi atau application_start ().
Kelas Konfigurasi Sampel:
public static class SearchConfig
{
public static void Init ( )
{
Epinova . ElasticSearch . Core . Conventions . Indexing . Instance
. ExcludeType < ErrorPage > ( )
. ExcludeType < StartPage > ( )
. ExcludeRoot ( 42 )
. IncludeFileType ( "pdf" )
. IncludeFileType ( "docx" )
. ForType < ArticlePage > ( ) . IncludeProperty ( x => x . Changed )
. ForType < ArticlePage > ( ) . IncludeField ( x => x . GetFoo ( ) )
. ForType < ArticlePage > ( ) . IncludeField ( "TenYearsAgo" , x => DateTime . Now . AddYears ( - 10 ) )
. ForType < ArticlePage > ( ) . EnableSuggestions ( x => x . Title )
. ForType < TagPage > ( ) . EnableSuggestions ( )
. ForType < ArticlePage > ( ) . EnableHighlighting ( x => x . MyField )
. ForType < ArticlePage > ( ) . StemField ( x => x . MyField ) ;
}
}Penjelasan tentang berbagai opsi:
ExcludeType : Jenis ini tidak akan diindeks. Kelas dasar dan antarmuka juga didukung. Hal yang sama dapat dicapai dengan mendekorasi tipe Anda dengan ExcludeFromSearchAttribute
ExcludeRoot : Node ini dan anak -anaknya tidak akan diindeks. Biasanya node-ID di page-tree episerver.
IncludeFileType : Menentukan ekstensi untuk jenis file yang harus diindeks. Lihat juga simpul <files> di konfigurasi.
ForType : Titik awal untuk aturan pengindeksan jenis tertentu. Tidak melakukan apa pun, tetapi memberikan akses ke opsi berikut:
IncludeField : mendefinisikan properti khusus yang akan diindeks. Misalnya metode ekstensi yang mengambil data eksternal atau melakukan agregasi yang kompleks.
EnableSuggestions : Menawarkan data AutoSuggest dari jenis ini, baik dari semua properti atau yang dipilih melalui ekspresi lambda.
IncludeProperty : Efek yang sama seperti mendekorasi properti dengan [dicari]. Dapat digunakan jika Anda tidak mengontrol sumber model.
EnableHighlighting : Tambahkan bidang tambahan yang akan disorot.
StemField : Menentukan bahwa properti harus dianalisis dalam bahasa saat ini. Properti bernama MainIntro , MainBody dan Description akan selalu dianalisis.
Modul ini mencoba untuk mengikuti konvensi yang sama dengan Episerver, yang berarti bahwa semua properti string tipe dan XhtmlString akan diindeks kecuali secara eksplisit didekorasi dengan [Searchable(false)] . Properti tambahan dapat diindeks dengan mendekorasi mereka dengan [Searchable] atau dengan konvensi di atas. Hiasi ContentArea dengan [Searchable] untuk mengindeks konten.
SearchResult result = service
. Search ( "bacon" )
. GetResults ( ) ; SearchResult result = service
. Search < ArticlePage > ( "bacon" )
. GetResults ( ) ; SearchResult result = service
. Search < ArticlePage > ( "bacon" )
. InField ( x => x . MainIntro )
. InField ( x => x . MainBody )
. InField ( x => x . MyCustomMethod ( ) )
. GetResults ( ) ;Mencari kata -kata yang diindeks dimulai dengan frasa:
string [ ] suggestions = service . GetSuggestions ( "baco" ) ;Dengan panjang default otomatis (disarankan):
SearchResult result = service
. Search < ArticlePage > ( "bacon" )
. Fuzzy ( )
. GetResults ( ) ;Dengan panjang spesifik:
SearchResult result = service
. Search < ArticlePage > ( "bacon" )
. Fuzzy ( 4 )
. GetResults ( ) ;Gunakan dengan hati -hati karena ini tidak mendukung fitur seperti Stemming.
SearchResult result = service
. WildcardSearch < ArticlePage > ( "*bacon*" )
. GetResults ( ) ; SearchResult result = service
. WildcardSearch < ArticlePage > ( "me?t" )
. GetResults ( ) ; SearchResult result = service
. SimpleQuerystringSearch < ArticlePage > ( "(bacon | ham) melt -cheese" )
. GetResults ( ) ;Dengan operator terbatas:
SearchResult result = service
. SimpleQuerystringSearch < ArticlePage > ( " " bacon melt " sandwi*" ,
defaultOperator : Operator . And ,
allowedOperators :
SimpleQuerystringOperators . Prefix |
SimpleQuerystringOperators . Phrase ) ;
)
. GetResults ( ) ;Lihat https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-simple-query-string-query.html untuk sintaks.
Menggunakan properti tipe Epinova.ElasticSearch.Core.Models.Properties.GeoPoint memungkinkan Anda untuk melakukan penyaringan berbasis geo.
Model contoh:
public class OfficePage : StandardPage
{
[ Display ]
public virtual double Lat { get ; set ; }
[ Display ]
public virtual double Lon { get ; set ; }
// Helper property, you could always roll an editor for this
public GeoPoint Location => new GeoPoint ( Lat , Lon ) ;
} Temukan titik di dalam area persegi berdasarkan sudut kiri atas dan kanan bawah.
var topLeft = ( 59.9277542 , 10.7190847 ) ;
var bottomRight = ( 59.8881646 , 10.7983952 ) ;
SearchResult result = service
. Get < OfficePage > ( )
. FilterGeoBoundingBox ( x => x . Location , , topLeft , bottomRight )
. GetResults ( ) ; Temukan titik di dalam lingkaran yang diberi titik tengah dan jarak jari -jari.
var center = ( 59.9277542 , 10.7190847 ) ;
var radius = "10km" ;
SearchResult result = service
. Get < OfficePage > ( )
. FilterGeoDistance ( x => x . Location , radius , center )
. GetResults ( ) ; Temukan poin di dalam poligon dengan jumlah poin yang sewenang -wenang. Poin poligon misalnya dapat berupa garis besar kota, negara atau jenis daerah lainnya.
var polygons = new [ ]
{
( 59.9702837 , 10.6149134 ) ,
( 59.9459601 , 11.0231964 ) ,
( 59.7789455 , 10.604809 )
} ;
SearchResult result = service
. Get < OfficePage > ( )
. FilterGeoPolygon ( x => x . Location , polygons )
. GetResults ( ) ;Temukan konten yang mirip dengan dokumen-id yang disediakan
SearchResult result = service
. MoreLikeThis ( "42" )
. GetResults ( ) ;Perdagangan:
SearchResult result = service
. MoreLikeThis ( "123__CatalogContent" )
. GetResults ( ) ;Parameter opsional:
minimumTermFrequency Frekuensi istilah minimum di bawah ini istilah akan diabaikan dari dokumen input. Default ke 1.
maxQueryTerms Jumlah maksimum dari istilah kueri yang akan dipilih. Meningkatkan nilai ini memberikan akurasi yang lebih besar dengan mengorbankan kecepatan eksekusi kueri. Default ke 25.
minimumDocFrequency Frekuensi dokumen minimum di bawah ini istilah akan diabaikan dari dokumen input. Default ke 3.
minimumWordLength Panjang kata minimum di bawah yang istilah akan diabaikan. Default ke 3.
Gawai:

Jika Anda tidak ingin mengecualikan jenis secara global, Anda hanya dapat melakukannya dalam konteks kueri:
SearchResult result = service
. Search < ArticlePage > ( "bacon" )
. Exclude < SaladPage > ( )
. GetResults ( ) ; Kecualikan node pada waktu kueri:
SearchResult result = service
. Search < ArticlePage > ( "bacon" )
. Exclude ( 42 )
. Exclude ( contentInstance )
. Exclude ( contentReference )
. GetResults ( ) ; Kueri menggunakan CurrentCulture sebagai default. Ini bisa ditimpa:
SearchResult result = service
. Search < ArticlePage > ( "bacon" )
. Language ( CultureInfo . GetCultureInfo ( "en" ) )
. GetResults ( ) ; Gunakan metode From() dan Size() untuk pagination, atau alias Skip() dan Take() :
SearchResult result = service
. Search < CoursePage > ( "foo" )
. From ( 10 )
. Size ( 20 )
. GetResults ( ) ; var query = service
. Search < CoursePage > ( "foo" )
. FacetsFor ( x => x . DepartmentID ) ; Faset akan dibuat dari filter yang saat ini diterapkan dan bukan seluruh hasil.
var query = service
. Search < CoursePage > ( "foo" )
. FacetsFor ( x => x . DepartmentID , usePostFilter : false ) ; Satu Nilai:
string selectedFilter = Request . Querstring [ "filter" ] ;
query = query . Filter ( p => p . DepartmentID , selectedFilter ) ;Satu nilai, dengan metode ekstensi:
string selectedFilter = Request . Querstring [ "filter" ] ;
query = query . Filter ( p => p . GetDepartmentID ( ) , selectedFilter ) ;Beberapa nilai:
string [ ] selectedFilters = Request . Querstring [ "filters" ] ;
query = query . Filter ( p => p . DepartmentID , selectedFilters ) ;Gunakan dan operator untuk menyaring semua filter:
string [ ] selectedFilters = Request . Querstring [ "filters" ] ;
query = query . Filter ( p => p . DepartmentID , selectedFilters , Operator . And ) ; SearchResult results = query . GetResults ( ) ; foreach ( FacetEntry facet in results . Facets )
{
// facet.Key = name of the property, ie. DepartmentID
// facet.Count = number of unique values for this facet
foreach ( FacetHit hit in facet . Hits )
{
// hit.Key = facet value
// hit.Count = number with this value
}
} Beberapa filter dapat dikelompokkan untuk membentuk pertanyaan yang lebih kompleks.
Dalam contoh di bawah ini, berikut ini harus benar untuk memberikan kecocokan:
Sizes adalah "xs" atau "xl"
ProductCategory adalah "pants"
Brand adalah "levis" atau "diesel"
query = query
. FilterGroup ( group => group
. Or ( page => page . Sizes ( ) , new [ ] { "xs" , "xl" } )
. And ( page => page . ProductCategory , "pants" )
. Or ( page => page . Brand , new [ ] { "levis" , "diesel" } )
) ; Untuk menyaring nilai -nilai tertentu, gunakan FilterMustNot
var query = service
. Search < PageData > ( "foo" )
. FilterMustNot ( x => x . Title , "bar" ) ; Untuk memfilter ACL pengguna saat ini, gunakan FilterByACL
var query = service
. Search < PageData > ( "foo" )
. FilterByACL ( ) ; EPiServer.Security.PrincipalInfo.Current akan digunakan secara default, tetapi PrincipalInfo khusus dapat disediakan jika diperlukan.
Untuk mencari dalam rentang nilai yang diberikan, gunakan fungsi Range .
Jenis yang didukung adalah DateTime , double , decimal dan long (termasuk konversi intr dari int , byte dll.)
SearchResult result = service
. Search ( "bacon" )
. Range ( x => x . StartPublish , DateTime . Now . Date , DateTime . Now . Date . AddDays ( 2 ) )
. GetResults ( ) ; SearchResult result = service
. Search ( "bacon" )
. Range ( x => x . MyNumber , 10 , 20 )
. GetResults ( ) ;Argumen yang kurang dari opsional.
SearchResult result = service
. Search ( "bacon" )
. Range ( x => x . MyNumber , 10 ) // Returns anything above 10
. GetResults ( ) ; Untuk mencari interval di dalam interval lain, properti Anda harus dari tipe Epinova.ElasticSearch.Core.Models.Properties.IntegerRange .
Saat ini int adalah satu -satunya jenis yang didukung.
SearchResult result = service
. Search ( "bacon" )
. Range ( x => x . MyRange , 10 , 20 )
. GetResults ( ) ; public class ArticlePage : StandardPage
{
[Display]
public virtual int From { get; set; }
[Display]
public virtual int To { get; set; }
public IntegerRange MyRange => new IntegerRange(From, To);
}
Jika suatu properti adalah tipe IDictionary<string, object> dan ditandai [Searchable] , itu akan diindeks sebagai object di Elasticsearch.
Ini berguna dalam skenario di mana Anda memiliki data nilai kunci dinamis yang harus diindeks, seperti dari pim-sistem.
Pendekatan Properti Standar:
public class ProductPage
{
[Searchable]
public IDictionary<string, object> Metadata { get; set; }
}
Data itu sendiri tidak akan dikembalikan, tetapi Anda dapat menanyakannya dan membuat segi:
SearchResult result = service
. Search < ProductPage > ( "bacon" )
. InField ( x => x . Metadata + ".SomeKey" )
. FacetsFor ( x => x . Metadata + ".SomeKey" )
. GetResults ( ) ;Properti Kustom:
public static class SearchConfig
{
public static void Init ( )
{
Epinova . ElasticSearch . Core . Conventions . Indexing . Instance
. ForType < ProductPage > ( ) . IncludeField ( "Metadata" , x => x . GetPimDataDictionary ( ) ) ;
}
}Pendekatan ini mengembalikan data:
SearchResult result = service
. Search < ProductPage > ( "bacon" )
. GetResults ( ) ;
var hit = result . Hits . First ( ) ;
var dict = hit . Custom [ "Metadata" ] as IDictionary < string , object > Properti dapat didorong dengan mendekorasi mereka dengan atribut Boost :
[ Boost ( 13 ) ]
public string Title { get ; set ; }... atau pada waktu kueri:
SearchResult result = service
. Search ( "bacon" )
. Boost ( x => x . MyProp , 3 )
. GetResults ( ) ;Jenis dapat diberikan dorongan positif atau negatif:
SearchResult result = service
. Search ( "bacon" )
. Boost < ArticlePage > ( 2 )
. GetResults ( ) ; SearchResult result = service
. Search ( "bacon" )
. Boost ( typeof ( ArticlePage ) , 2 )
. GetResults ( ) ; SearchResult result = service
. Search ( "bacon" )
. Boost < ArticlePage > ( - 3 )
. GetResults ( ) ;Anda juga dapat meningkatkan hit tergantung pada lokasinya di pohon halaman:
SearchResult result = service
. Search ( "bacon" )
. BoostByAncestor ( new ContentReference ( 42 ) , 2 )
. GetResults ( ) ; Properti tanggal dapat dinilai lebih rendah tergantung pada nilainya, dengan menggunakan fungsi Decay . Dengan cara ini Anda dapat mempromosikan artikel yang lebih baru dibandingkan yang lebih tua.
SearchResult result = service
. Search ( "bacon" )
. Decay ( x => x . StartPublish , TimeSpan . FromDays ( 7 ) )
. GetResults ( ) ;Setiap kali interval tanggal (argumen ke -2) terjadi, 0,5 poin akan dikurangi dari skor. Dalam contoh di atas, 0,5 poin akan dikurangi setelah 7 hari, 1 poin setelah 14 hari, dan seterusnya.
Gunakan .UseBestBets() pada kueri Anda untuk mencetak konten yang dipilih lebih tinggi dari biasanya.
SearchResult result = service
. Search ( "bacon" )
. UseBestBets ( )
. GetResults ( ) ;Taruhan terbaik dapat dikelola melalui mesin pencari menu tertanam -> taruhan terbaik.

Statistik sederhana dapat dikumpulkan menggunakan fungsi .Track() . Ini akan melacak berapa kali istilah ditanya dan apakah itu mengembalikan hit.
SearchResult result = service
. Search ( "bacon" )
. Track ( )
. GetResults ( ) ; 
Catatan: Jika string koneksi Anda tidak bernama EPiServerDB , Anda harus memberikan namanya di trackingConnectionStringName -Configuration lihat Instalasi
Stemming secara default diterapkan pada semua properti tipe XhtmlString , atau yang bernama MainIntro atau MainBody .
Bahasa didasarkan pada bahasa konten. Properti lain dari string tipe dapat dibawa dengan mendekorasi mereka dengan Stem -attribute:
[ Stem ]
public string Title { get ; set ; } Untuk daftar konten dari jenis tertentu tanpa penilaian atau analisis, gunakan fungsi Get . Ini dapat digunakan bersama dengan SortBy untuk daftar sederhana.
SearchResult result = service
. StartFrom ( somePageLink )
. Get < ArticlePage > ( )
. GetResults ( ) ; Penyortiran biasanya dilakukan oleh Elasticsearch berdasarkan skor setiap pertandingan. Penyortiran manual hanya boleh digunakan dalam skenario di mana penilaian tidak relevan, misalnya saat menggunakan fungsi Get yang disebutkan sebelumnya.
SearchResult result = service
. Get < ArticlePage > ( )
. SortBy ( p => p . StartPublish )
. ThenBy ( p => p . Foo )
. ThenBy ( p => p . Bar )
. GetResults ( ) ; Saat menyortir di geopoint, ada satu lagi argumen wajib; compareTo . Item akan dibandingkan dengan koordinat ini, dan jarak yang dihasilkan akan digunakan sebagai nilai sortir.
Untuk kontrol absolut, Anda dapat menggunakan skrip untuk mengurutkan dokumen. Perhatikan bahwa ini mungkin mempengaruhi kinerja.
Contoh penyortiran berdasarkan cap waktu tertentu:
var timestamp = new DateTimeOffset ( new DateTime ( 2019 , 1 , 1 ) ) . ToUnixTimeMilliseconds ( ) ;
var script = $ "doc['StartPublish'].date.getMillis() > { timestamp } ? 0 : 1" ;
SearchResult result = service
. Get < ArticlePage > ( )
. SortByScript ( script , true , "number" )
. GetResults ( ) ;Lihat https://www.elastic.co/guide/en/elasticsearch/painless/current/index.html untuk sintaks skrip.
Filter sirap disertakan yang dapat menyarankan kata -kata serupa yang ditemukan dalam indeks saat mencari kata -kata yang salah eja.
Setiap saran yang ditemukan akan dimasukkan dalam properti DidYouMean dari hasil pencarian:
SearchResult result = service
. Search ( "alloi" )
. GetResults ( ) ;
string [ ] didYouMean = result . DidYouMean ; // [ "alloy", "all" ] Properti apa pun yang harus bertindak sebagai sumber untuk saran harus ditandai dengan [DidYouMeanSource] .
public class StandardPage : SitePageData
{
[ DidYouMeanSource ]
public virtual XhtmlString MainBody { get ; set ; }
} Hasil yang dikembalikan oleh GetResults() tidak memiliki pengetahuan tentang Episerver. Gunakan fungsi GetContentResults() dalam konteks Episerver.
Ini secara otomatis akan menerapkan filter FilterAccess , FilterPublished dan FilterTemplate .
IEnumerable < IContent > content = service
. Search < CoursePage > ( text )
. GetContentResults ( ) ; Jika Anda ingin menggunakan salah satu penyedia yang disertakan saat mencari dalam mode Edit, buka CMS -> Admin -> Config -> Pengaturan Alat -> Konfigurasi Pencarian.
Centang penyedia dan seret mereka ke bagian atas daftar.
Sinonim dapat dikelola dari mesin pencari menu -> Sinonim.
Konten akan secara otomatis diindeks ulang saat melakukan operasi umum seperti penerbitan, bergerak dan menghapus.
Untuk melakukan pengindeksan awal dari semua konten, jalankan tugas yang dijadwalkan «Elasticsearch: Indeks Konten CMS»
Indeks ulang juga dapat dipicu secara manual pada konten individual melalui alat-menu:

... atau melalui menu konteks di pohon halaman:

Hasil yang dikembalikan oleh GetResults() tidak memiliki pengetahuan tentang Episerver. Gunakan fungsi GetCatalogResults() dalam konteks perdagangan Episerver. Ini akan secara otomatis memilih indeks yang benar dan menerapkan filter FilterAccess , FilterPublished dan FilterTemplate .
IEnumerable < ProductContent > content = service
. Search < ProductContent > ( text )
. GetCatalogResults ( ) ; Konten akan secara otomatis diindeks ulang saat melakukan operasi umum seperti penerbitan, bergerak dan menghapus.
Untuk melakukan pengindeksan awal dari semua konten, jalankan tugas yang dijadwalkan «Elasticsearch: Index Commerce Content»
Anda dapat beralih antara tokenizer normal dan tri -gram (hardcoded ke min = 3, max = 3, token = digit, char, per rekomendasi elastis) melalui mesin pencari menu -> administrasi dan status.
Gunakan fungsi Highlight() untuk mendapatkan kutipan 150 karakter dari tempat pertandingan terjadi dalam teks.
SearchResult result = service
. Search ( "bacon" )
. Highlight ( )
. GetContentResults ( ) ; Sorotan secara default diaktifkan pada properti bernama MainIntro , MainBody , Attachment dan Description .
Penanda default adalah <mark>
Anda dapat menyesuaikan perilaku ini dengan opsi konfigurasi berikut:
Indexing . Instance . ForType < ArticlePage > ( ) . EnableHighlighting ( x => x . MyField ) ;
Indexing . Instance . SetHighlightFragmentSize ( 42 ) ;
Indexing . Instance . SetHighlightTag ( "blink" ) ; Hasilnya dapat ditemukan di properti Highlight dari setiap hit.
Gunakan fungsi Bulk untuk mengindeks konten khusus.
Contoh:
var obj1 = new ComplexType { StringProperty = "this is myobj 1" } ;
var obj2 = new ComplexType { StringProperty = "this is myobj 2" } ;
var obj3 = new ComplexType { StringProperty = "this is myobj 3" } ;
ICoreIndexer indexer = ServiceLocator . Current . GetInstance < ICoreIndexer > ( ) ; // Can also be injected
BulkBatchResult bulk = indexer . Bulk ( new [ ]
{
new BulkOperation ( obj1 , "no" ) ,
new BulkOperation ( obj2 , "no" ) ,
new BulkOperation ( obj3 , "no" )
} ) ;
var results = _service
. Search < ComplexType > ( "myobj" )
. InField ( x => x . StringProperty )
. GetCustomResults ( ) ; Jika Anda lebih suka indeks khusus untuk menghindari tabrakan misalnya, ini harus disediakan saat mengindeks dan mencari:
var obj1 = new ComplexType { StringProperty = "this is myobj 1" } ;
var obj2 = new ComplexType { StringProperty = "this is myobj 2" } ;
var obj3 = new ComplexType { StringProperty = "this is myobj 3" } ;
ICoreIndexer indexer = ServiceLocator . Current . GetInstance < ICoreIndexer > ( ) ; // Can also be injected
string indexName = "my-uber-custom-name-no" ;
BulkBatchResult bulk = indexer . Bulk ( new [ ]
{
new BulkOperation ( obj1 , "no" , index : indexName ) ,
new BulkOperation ( obj2 , "no" , index : indexName ) ,
new BulkOperation ( obj3 , "no" , index : indexName )
} ) ;
var results = _service
. UseIndex ( indexName )
. Search < ComplexType > ( "myobj" )
. InField ( x => x . StringProperty )
. GetCustomResults ( ) ; Epinova.elasticsearch menggunakan HttpClient standar untuk menghubungi Elasticsearch. Terkadang diperlukan untuk menangani pesan yang dikirim secara berbeda. Misalnya permintaan penandatanganan untuk layanan cloud.
Jika Anda ingin beberapa httpmessageHandlers, kami sarankan merantai mereka sebelum mengatur.
Misalnya:
MessageHandler . Instance . SetMessageHandler ( new AWSHandler ( ) ) ; GetCustomResults mengembalikan objek yang diketik dengan kuat sebagai lawan dari GetContentResults , yang hanya mengembalikan ID.
Objek khusus tidak memerlukan properti Id (atau argumen yang sesuai dalam CTOR BulkOperation ), tetapi ini disarankan jika Anda ingin kontrol atas versi dan pembaruan/penghapusan.