This commit is contained in:
Jürgen Mummert
2025-12-27 22:26:47 +01:00
parent 4cf0d7315b
commit 2832da4736
2 changed files with 32 additions and 44 deletions
@@ -2,7 +2,7 @@
Meilisearch Frontend Search Meilisearch Frontend Search
Contao 5 Frontend Module Template Contao 5 Frontend Module Template
#} #}
<!-- indexer::stop -->
<div <div
class="meilisearch-search" class="meilisearch-search"
data-limit="{{ meiliLimit }}" data-limit="{{ meiliLimit }}"
@@ -27,7 +27,7 @@ Contao 5 Frontend Module Template
<div id="meilisearch-results" class="meilisearch-results"></div> <div id="meilisearch-results" class="meilisearch-results"></div>
</div> </div>
<!-- indexer::continue -->
<script type="module"> <script type="module">
import MeiliSearch from 'https://cdn.jsdelivr.net/npm/meilisearch@latest/dist/bundles/meilisearch.esm.js'; import MeiliSearch from 'https://cdn.jsdelivr.net/npm/meilisearch@latest/dist/bundles/meilisearch.esm.js';
+28 -40
View File
@@ -34,7 +34,6 @@ class MeilisearchIndexService
*/ */
public function run(): void public function run(): void
{ {
// Contao vollständig initialisieren (CLI & Cron!)
$this->framework->initialize(); $this->framework->initialize();
$host = (string) Config::get('meilisearch_host'); $host = (string) Config::get('meilisearch_host');
@@ -48,44 +47,44 @@ class MeilisearchIndexService
$this->client = new Client($host, $apiKey); $this->client = new Client($host, $apiKey);
$index = $this->client->index($this->indexName); $index = $this->client->index($this->indexName);
// 🔑 PRIMARY KEY EINMALIG FESTLEGEN
try { try {
$index->updateSettings([ $index->updateSettings(['primaryKey' => 'id']);
'primaryKey' => 'id', } catch (\Throwable) {}
]);
} catch (\Throwable) {
// bewusst ignorieren
}
// ✅ Index-Settings sicherstellen
$this->ensureIndexSettings($index); $this->ensureIndexSettings($index);
// 🔄 Index leeren (Settings bleiben erhalten)
$index->deleteAllDocuments(); $index->deleteAllDocuments();
// 📄 Inhalte indexieren
$this->indexTlSearch($index); $this->indexTlSearch($index);
$this->indexTlSearchPdf($index); $this->indexTlSearchPdf($index);
} }
/**
* Relevanz- & Sortierlogik für Meilisearch
*/
private function ensureIndexSettings(Indexes $index): void private function ensureIndexSettings(Indexes $index): void
{ {
$index->updateSettings([ $index->updateSettings([
'searchableAttributes' => [ 'searchableAttributes' => ['title', 'keywords', 'text'],
'title', 'sortableAttributes' => ['priority', 'startDate'],
'keywords',
'text',
],
'sortableAttributes' => [
'priority',
'startDate',
],
]); ]);
} }
/**
* ⛔ MEILISEARCH_META aus Text entfernen
*/
private function stripMeilisearchMeta(string $text): string
{
$text = preg_replace(
'/⟦MEILISEARCH_META⟧.*?⟦\/MEILISEARCH_META⟧/su',
'',
$text
);
// Text normalisieren
$text = preg_replace('/\s{2,}/u', ' ', $text);
$text = preg_replace('/\n{2,}/u', "\n", $text);
return trim($text);
}
/** /**
* startDate aus schema.org Event extrahieren * startDate aus schema.org Event extrahieren
*/ */
@@ -105,16 +104,12 @@ class MeilisearchIndexService
continue; continue;
} }
// ✅ Contao-JSON-LD (vollqualifiziert)
if (!empty($entry['https://schema.org/startDate'])) { if (!empty($entry['https://schema.org/startDate'])) {
$ts = strtotime($entry['https://schema.org/startDate']); return strtotime($entry['https://schema.org/startDate']) ?: null;
return $ts ?: null;
} }
// 🛟 Fallback (falls Contao das irgendwann ändert)
if (!empty($entry['startDate'])) { if (!empty($entry['startDate'])) {
$ts = strtotime($entry['startDate']); return strtotime($entry['startDate']) ?: null;
return $ts ?: null;
} }
} }
@@ -139,22 +134,21 @@ class MeilisearchIndexService
foreach ($rows as $row) { foreach ($rows as $row) {
$type = $this->detectTypeFromMeta($row['meta'] ?? null); $type = $this->detectTypeFromMeta($row['meta'] ?? null);
// 📅 Event-Startdatum einmal ermitteln
$eventStart = null; $eventStart = null;
if ($type === 'event') { if ($type === 'event') {
$eventStart = $this->extractEventStartDate($row['meta'] ?? null); $eventStart = $this->extractEventStartDate($row['meta'] ?? null);
// ⛔ Vergangene Events überspringen (wenn nicht erlaubt)
if (!$indexPastEvents && $eventStart !== null && $eventStart < $today) { if (!$indexPastEvents && $eventStart !== null && $eventStart < $today) {
continue; continue;
} }
} }
$cleanText = $this->stripMeilisearchMeta((string) $row['text']);
$doc = [ $doc = [
'id' => $type . '_' . $row['id'], 'id' => $type . '_' . $row['id'],
'type' => $type, 'type' => $type,
'title' => $row['title'], 'title' => $row['title'],
'text' => $row['text'], 'text' => $cleanText,
'url' => $row['url'], 'url' => $row['url'],
'protected' => (bool) $row['protected'], 'protected' => (bool) $row['protected'],
'checksum' => $row['checksum'], 'checksum' => $row['checksum'],
@@ -162,12 +156,10 @@ class MeilisearchIndexService
'priority' => (int) ($row['priority'] ?? 0), 'priority' => (int) ($row['priority'] ?? 0),
]; ];
// 📅 startDate nur für Events setzen
if ($eventStart !== null) { if ($eventStart !== null) {
$doc['startDate'] = $eventStart; $doc['startDate'] = $eventStart;
} }
// 🖼️ Bild aus UUID erzeugen
if (!empty($row['imagepath'])) { if (!empty($row['imagepath'])) {
$imagePath = $this->imageHelper->resolveImagePath($row['imagepath']); $imagePath = $this->imageHelper->resolveImagePath($row['imagepath']);
if ($imagePath !== null) { if ($imagePath !== null) {
@@ -204,7 +196,7 @@ class MeilisearchIndexService
'id' => $fileType . '_' . $row['id'], 'id' => $fileType . '_' . $row['id'],
'type' => $fileType, 'type' => $fileType,
'title' => $row['title'], 'title' => $row['title'],
'text' => $row['text'], 'text' => $this->stripMeilisearchMeta((string) $row['text']),
'url' => $row['url'], 'url' => $row['url'],
'checksum' => $row['checksum'], 'checksum' => $row['checksum'],
'poster' => self::FILETYPE_ICON_MAP[$fileType] 'poster' => self::FILETYPE_ICON_MAP[$fileType]
@@ -215,9 +207,6 @@ class MeilisearchIndexService
$index->addDocuments($documents); $index->addDocuments($documents);
} }
/**
* Typ (page | event | news) aus meta erkennen
*/
private function detectTypeFromMeta(?string $meta): string private function detectTypeFromMeta(?string $meta): string
{ {
if (!$meta) { if (!$meta) {
@@ -233,7 +222,6 @@ class MeilisearchIndexService
if (($entry['@type'] ?? null) === 'https://schema.org/Event') { if (($entry['@type'] ?? null) === 'https://schema.org/Event') {
return 'event'; return 'event';
} }
if (($entry['@type'] ?? null) === 'https://schema.org/NewsArticle') { if (($entry['@type'] ?? null) === 'https://schema.org/NewsArticle') {
return 'news'; return 'news';
} }