Typsense är ett bra alternativ med öppen källkod för Algolia. Med tanke på att Algolia har ett ganska dyrt prispaket kan det vara värt att ta en titt på Typesense.
Utöver det har den redan några integrationer med kända paket som Instantsearch.js och Laravel Scout.
Det började nyligen, så det saknas fortfarande några exempel i dokumentationen. Det är därför jag har skrivit detta inlägg:
Använder Typesense för Laravel
Vad som är bra är att det finns ett Laravel Scout-paket tillgängligt: https://github.com/devloopsnet/laravel-scout-typesense-engine
Åtgärda de första Typesense-felen med Laravel:
Troligtvis kommer du att få fel när du använder standardinställningarna som beskrivs i Typesense Laravel Scout-paketet:
{"meddelande": "Dokumentets `id`-fält ska vara en sträng."}Det går att lösa genom att konvertera id:t till en sträng i den sökbara arrayen:
/** * Hämta den indexerbara datamatrisen för modellen. * * @return array */ public function toSearchableArray() { $array = $this->toArray();
// Typesense specifik
if (config('scout.driver') == 'typesensesearch') {
$array['id'] = (sträng)$array['id']; $array['created_at'] = (heltal)\Carbon::parse($array['created_at'])->tidsstämpel;
}
returnera $array;
}Observera att jag också konverterade värdet create_at datetime till ett tidsstämpel heltal, så att Typesense enkelt kunde sortera på heltalsvärdet för datumet.
Lägger till Instantsearch.js Typesense-adaptern till Laravel
Du kan följa stegen som beskrivs av Instruktioner för Typesense Adapter. Glöm inte heller att npm installera algoliasearch och instantsearch.js .
Insättning i Laravel Mix
Du kan infoga följande kod i filen webpack.mix.js för Laravel Mix:
mix.extract(['algoliasearch', 'instantsearch.js', 'typesense-instantsearch-adapter']) .js(['resources/js/app.js'], 'public/js');I dina resources/js/app.js gör du även importen klar:
importera instantsearch från "instantsearch.js"; window.instantsearch = instantsearch; importera { searchBox, hits, index } från "instantsearch.js/es/widgets"; window.searchBox = sökruta; window.hits = träffar; window.index = index; importera { connectAutocomplete } från 'instantsearch.js/es/connectors'; window.connectAutocomplete = connectAutocomplete; importera TypesenseInstantSearchAdapter från "typesense-instantsearch-adapter"; window.TypesenseInstantSearchAdapter = TypesenseInstantSearchAdapter;Observera att jag även har inkluderat index och connectAutocomplete som krävs för Autocomplete-widgeten. Om du inte planerar att använda dem kan du utelämna dem.
Kör Laravel Mix med (använd även npm installation om Mix aldrig har initierats):
npm kör devLägg till de genererade mixfilerna i din huvudlayoutbladsfil:
Sedan kan du helt enkelt infoga träffarna och sökrutan:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/themes/reset-min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/themes/algolia-min.css">
<div id="hits"></div>
<div id="searchbox"></div>
<script>
const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
server: {
apiKey: "{{ env('TYPESENSE_SEARCH_KEY') }}", // Be sure to use the search-only-api-key
nodes: [
{
host: "{{ env('TYPESENSE_HOST') }}",
port: "443",
protocol: "https"
}
]
},
// The following parameters are directly passed to Typesense's search API endpoint.
// So you can pass any parameters supported by the search endpoint below.
// queryBy is required.
additionalSearchParameters: {
queryBy: "name"
}
});
const searchClient = typesenseInstantsearchAdapter.searchClient;
const search = instantsearch({
searchClient,
indexName: "products"
});
// Create the custom widget
const customAutocomplete = connectAutocomplete(
renderAutocomplete
);
// Instantiate the custom widget
search.addWidgets([
index({ searchClient, indexName: 'autolandings' }),
customAutocomplete({
container: document.querySelector('#autocomplete'),
})
]);
search.start();
</script>Jag har lagt till CSS-temat för instantsearch.js för att ge det lite grundläggande stil. Den här verkar inte fungera för Autocomplete ännu. Du måste styla den här helt själv (så vitt jag vet).
Hur man använder Instantsearch.js Autocomplete med Typesense
Typesense skrev en adapter som fungerar med Instantsearch.js för Algolia. Den har några grundläggande exempel för att använda komponenten träffar och sökruta.
I vissa fall vill du utöka denna funktionalitet. Till exempel, om du vill använda Instantsearch.js autoslutförande funktionalitet måste du skriva ytterligare kod. För att göra en grundläggande autoslutförandefunktion med flera index kan du använda den här koden:
Använder flera index och Autocomplete för Instantsearch.js
I det här exemplet har jag kopierat koden från Algolias webbplats Instantsearch.js Autocomplete och integrerat Typesense-adaptern:
<div id="autocomplete"></div>
<script>
const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
server: {
apiKey: "{{ env('TYPESENSE_SEARCH_KEY') }}", // Be sure to use the search-only-api-key
nodes: [
{
host: "{{ env('TYPESENSE_HOST') }}",
port: "443",
protocol: "https"
}
]
},
// The following parameters are directly passed to Typesense's search API endpoint.
// So you can pass any parameters supported by the search endpoint below.
// queryBy is required.
additionalSearchParameters: {
queryBy: "name"
}
});
const searchClient = typesenseInstantsearchAdapter.searchClient;
const search = instantsearch({
searchClient,
indexName: "products"
});
// Helper for the render function
const renderIndexListItem = ({ indexId, hits }) => `
<li>
Index: ${indexId}
<ol>
${hits
.map(
(hit, hitIndex) =>
`
<li>
<p>${instantsearch.highlight({ attribute: 'name', hit })}</p>
<button
type="button"
class="btn-add-to-cart"
data-index-id="${indexId}"
data-hit-index="${hitIndex}"
>
Add to Cart
</button>
</li>
`
)
.join('')}
</ol>
</li>
`;
// Create the render function
const renderAutocomplete = (renderOptions, isFirstRender) => {
const { indices, currentRefinement, refine, widgetParams } = renderOptions;
if (isFirstRender) {
const input = document.createElement('input');
const ul = document.createElement('ul');
input.addEventListener('input', event => {
refine(event.currentTarget.value);
});
widgetParams.container.appendChild(input);
widgetParams.container.appendChild(ul);
ul.addEventListener('click', (event) => {
if (event.target.className === 'btn-add-to-cart') {
const indexId = event.target.getAttribute('data-index-id');
const hitIndex = event.target.getAttribute('data-hit-index');
const index = indices.find(index => index.indexId === indexId);
const hit = index.hits[hitIndex];
index.sendEvent('conversion', hit, 'Product Added');
}
});
}
widgetParams.container.querySelector('input').value = currentRefinement;
widgetParams.container.querySelector('ul').innerHTML = indices
.map(renderIndexListItem)
.join('');
};
// Create the custom widget
const customAutocomplete = connectAutocomplete(
renderAutocomplete
);
// Instantiate the custom widget
search.addWidgets([
index({ searchClient, indexName: 'landings' }),
customAutocomplete({
container: document.querySelector('#autocomplete'),
})
]);
search.start();
</script>Glöm inte att fylla i TYPESENSE_SEARCH_KEY och TYPESENSE_HOST i dina miljövariabler. Och ersätt de första indexprodukterna med ditt önskade index. Ersätt "landningar" med önskat andra index. Du kan lägga till fler index genom att lägga till:
index({ searchClient, indexName: 'anotherIndex' }),till search.AddWidgets-delen.
Tänk på att vi också måste importera autokompletteringsanslutningen och indexkomponentwidgeten via Laravel Mix.
Senast uppdaterad 8 oktober 2020
