Suche mit Typesense für Laravel Scout

Verwenden Sie Typesense als Suchanbieter für Laravel Scout und Instantsearch.

Typesense ist eine großartige Open-Source-Alternative für Algolia. Da Algolia ein ziemlich teures Preispaket hat, könnte es sich lohnen, einen Blick auf Typesense zu werfen.

Darüber hinaus verfügt es bereits über einige Integrationen mit bekannten Paketen wie Instantsearch.js und Laravel-Scout.

Es ist erst vor kurzem gestartet, daher fehlen in der Dokumentation noch einige Beispiele. Aus diesem Grund habe ich diesen Beitrag geschrieben:

Typesense für Laravel verwenden

Das Tolle ist, dass ein Laravel Scout-Paket verfügbar ist: https://github.com/devloopsnet/laravel-scout-typesense-engine

Beheben der ersten Typesense-Fehler mit Laravel:

Höchstwahrscheinlich werden Sie Fehlermeldungen erhalten, wenn Sie die Standardeinstellungen verwenden, wie sie im Typesense Laravel Scout-Paket beschrieben sind:

{"message": "Das `id`-Feld des Dokuments sollte eine Zeichenfolge sein."}

Dies kann gelöst werden, indem die ID in einen String im durchsuchbaren Array konvertiert wird:

/** * Holen Sie sich das indizierbare Datenarray für das Modell. * * @return array */ public function toSearchableArray() { $array = $this->toArray();
   // Typesense-spezifisch
   wenn (Konfiguration('scout.driver') == 'typesensesearch') {
      $array['id'] = (Zeichenfolge)$array['id']; $array['erstellt am'] = (Ganzzahl)\Carbon::parse($array['erstellt am'])->Zeitstempel;
   }
   gibt $array zurück;
}

Beachten Sie, dass ich auch den Datums-/Uhrzeitwert „created_at“ in eine Zeitstempel-Ganzzahl konvertiert habe, damit Typesense problemlos nach dem Ganzzahlwert des Datums sortieren kann.

Hinzufügen des Instantsearch.js Typesense-Adapters zu Laravel

Sie können die Schritte wie beschrieben befolgen. Anleitung zum Typesense-Adapter. Vergessen Sie auch nicht, algoliasearch und instantsearch.js mit npm zu installieren.

Einfügen in Laravel Mix

Sie können den folgenden Code in die Datei webpack.mix.js für Laravel Mix einfügen:

mix.extract(['algoliasearch', 'instantsearch.js', 'typesense-instantsearch-adapter']) .js(['resources/js/app.js'], 'public/js');

Bereiten Sie in Ihren resources/js/app.js auch die Importe vor:

importiere Instantsearch aus „instantsearch.js“; window.instantsearch = Instantsearch; importiere { Suchfeld, Treffer, Index } aus „instantsearch.js/es/widgets“; window.searchBox = Suchfeld; window.hits = Treffer; window.index = Index; importiere { connectAutocomplete } aus „instantsearch.js/es/connectors“; window.connectAutocomplete = connectAutocomplete; importiere TypesenseInstantSearchAdapter aus „typesense-instantsearch-adapter“; window.TypesenseInstantSearchAdapter = TypesenseInstantSearchAdapter;

Beachten Sie, dass ich auch index und connectAutocomplete eingeschlossen habe, die für das Autocomplete-Widget erforderlich sind. Wenn Sie diese nicht verwenden möchten, können Sie sie weglassen.

Führen Sie Laravel Mix mit aus (verwenden Sie auch npm install, wenn Mix noch nie initialisiert wurde):

npm-Ausführung dev

Fügen Sie in Ihrer Haupt-Layout-Blade-Datei die generierten Mix-Dateien hinzu:

Anschließend kannst Du die Treffer einfach in das Suchfeld einfügen:

<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>

Ich habe das CSS-Design von instantsearch.js hinzugefügt, um ihm ein grundlegendes Styling zu verleihen. Dies scheint für Autocomplete noch nicht zu funktionieren. Sie müssen das Design (soweit ich weiß) vollständig selbst erstellen.

So verwenden Sie Instantsearch.js Autocomplete mit Typesense

Typesense hat einen Adapter geschrieben, der funktioniert mit Instantsearch.js für Algolia. Es hat einige grundlegende Beispiele um die Treffer- und Suchfeldkomponente zu verwenden.

In manchen Fällen möchten Sie diese Funktionalität erweitern. Wenn Sie beispielsweise die Instantsearch.js automatische Vervollständigung Funktionalität müssen Sie zusätzlichen Code schreiben. Um eine grundlegende Autovervollständigungsfunktion mit mehreren Indizes zu erstellen, können Sie diesen Code verwenden:

Verwenden mehrerer Indizes und Autocomplete für Instantsearch.js

In diesem Beispiel habe ich den Code von der Instantsearch.js Autocomplete-Website von Algolia kopiert und den Typesense-Adapter integriert:

<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>

Vergessen Sie nicht, TYPESENSE_SEARCH_KEY und TYPESENSE_HOST in Ihren Umgebungsvariablen auszufüllen. Und ersetzen Sie den ersten Index „products“ durch Ihren gewünschten Index. Ersetzen Sie „landings“ durch Ihren gewünschten zweiten Index. Sie können weitere Indizes hinzufügen, indem Sie Folgendes hinzufügen:

index({ Suchclient, indexName: 'andererIndex' }),

zum Teil search.AddWidgets.

Beachten Sie, dass wir auch den Autocomplete-Connector und das Indexkomponenten-Widget über Laravel Mix importieren müssen.

Einen Kommentar hinterlassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

de_DEDeutsch
Nach oben blättern