Typesense is een geweldig open-source alternatief voor AlgoliaAangezien Algolia een vrij duur pakket heeft, kan het de moeite waard zijn om naar Typesense te kijken.
Bovendien heeft het al een aantal integraties met bekende pakketten zoals Direct zoeken.js en Laravel-verkenner.
Het is pas geleden begonnen, dus de documentatie mist nog wat voorbeelden. Daarom heb ik dit bericht geschreven:
Typesense gebruiken voor Laravel
Het mooie is dat er een Laravel Scout-pakket beschikbaar is: https://github.com/devloopsnet/laravel-scout-typesense-engine
De eerste Typesense-fouten met Laravel oplossen:
U krijgt hoogstwaarschijnlijk foutmeldingen wanneer u de standaardinstellingen gebruikt zoals beschreven in het Typesense Laravel Scout-pakket:
{"message": "Het `id`-veld van het document moet een tekenreeks zijn."}
Dit is op te lossen door de id om te zetten in een string in de Searchable Array:
/** * Haal de indexeerbare gegevensarray voor het model op. * * @return array */ public function toSearchableArray() { $array = $this->toArray();// Typesense specifiek
als (config('scout.driver') == 'typesensesearch') {
$array['id'] = (tekenreeks)$array['id']; $array['gemaakt_op'] = (geheel getal)\Carbon::parse($array['gemaakt_op'])->timestamp;
}
retourneer $array;
}
Merk op dat ik ook de datetime-waarde created_at heb omgezet naar een tijdstempel-integer, zodat Typesense eenvoudig kan sorteren op de gehele waarde van de datum.
De Instantsearch.js Typesense Adapter toevoegen aan Laravel
U kunt de stappen volgen zoals beschreven door de Instructies voor Typesense-adapterVergeet ook niet om npm algoliasearch en instantsearch.js te installeren.
Invoegen in Laravel Mix
U kunt de volgende code invoegen in het bestand webpack.mix.js voor Laravel Mix:
mix.extract(['algoliasearch', 'instantsearch.js', 'typesense-instantsearch-adapter']) .js(['resources/js/app.js'], 'public/js');
Maak in je resources/js/app.js ook de imports gereed:
importeer instantsearch van "instantsearch.js"; window.instantsearch = instantsearch; importeer { searchBox, hits, index } van "instantsearch.js/es/widgets"; window.searchBox = searchBox; window.hits = hits; window.index = index; importeer { connectAutocomplete } van 'instantsearch.js/es/connectors'; window.connectAutocomplete = connectAutocomplete; importeer TypesenseInstantSearchAdapter van "typesense-instantsearch-adapter"; window.TypesenseInstantSearchAdapter = TypesenseInstantSearchAdapter;
Let op dat ik ook index en connectAutocomplete heb toegevoegd, die vereist zijn voor de Autocomplete Widget. Als u deze niet van plan bent te gebruiken, kunt u ze weglaten.
Voer Laravel Mix uit met (gebruik ook npm install als Mix nog nooit is geïnitialiseerd):
npm run-ontwikkeling
Voeg de gegenereerde mixbestanden toe aan uw hoofdlay-outbladbestand:
Vervolgens kunt u eenvoudig de resultaten en het zoekvak invoegen:
<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>
Ik heb de CSS-thema's van instantsearch.js toegevoegd om het wat basisstijl te geven. Deze lijkt nog niet te werken voor Autocomplete. Je moet deze helemaal zelf stylen (voor zover ik weet).
Hoe Instantsearch.js Autocomplete met Typesense te gebruiken
Typesense heeft een adapter geschreven die werkt met Direct zoeken.js voor Algolia. Het heeft wat basisvoorbeelden om het hits- en searchBox-component te gebruiken.
In sommige gevallen wilt u deze functionaliteit uitbreiden. Bijvoorbeeld, als u de Instantsearch.js automatisch aanvullen functionaliteit moet u extra code schrijven. Om een basis autocomplete functionaliteit met meerdere indices te maken kunt u deze code gebruiken:
Meerdere indices en automatisch aanvullen gebruiken voor Instantsearch.js
In dit voorbeeld heb ik de code van de Instantsearch.js Autocomplete-website van Algolia gekopieerd en de Typesense-adapter geïntegreerd:
<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>
Vergeet niet om de TYPESENSE_SEARCH_KEY en de TYPESENSE_HOST in uw omgevingsvariabelen in te vullen. En vervang de eerste indexproducten met uw gewenste index. Vervang 'landings' met uw gewenste tweede index. U kunt nog meer indices toevoegen door het volgende toe te voegen:
index({ searchClient, indexName: 'anotherIndex' }),
naar het search.AddWidgets gedeelte.
Houd er rekening mee dat we ook de autocomplete connector en de index component widget via Laravel Mix moeten importeren.