Files
timebank-cc-public/scripts/test-exact-search.php
Ronald Huynen 2547717edb Initial commit
2026-03-23 21:37:59 +01:00

173 lines
5.5 KiB
PHP
Executable File

<?php
require __DIR__.'/vendor/autoload.php';
$app = require_once __DIR__.'/bootstrap/app.php';
$app->make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap();
echo "=== EXACT MAINSEARCHBAR SEARCH TEST ===" . PHP_EOL . PHP_EOL;
$searchTerm = 'event';
$locale = 'en';
$currentTime = now()->toISOString();
// Build exact query from MainSearchBar
use ONGR\ElasticsearchDSL\Query\Compound\BoolQuery;
use ONGR\ElasticsearchDSL\Query\FullText\MultiMatchQuery;
$postsBoolQuery = new BoolQuery();
// Class name filter
$postsBoolQuery->add(
new \ONGR\ElasticsearchDSL\Query\TermLevel\TermQuery('__class_name', 'App\Models\Post'),
BoolQuery::MUST
);
// Search fields
$postSearchFields = [
'post_translations.title_' . $locale . '^3',
'post_translations.content_' . $locale . '^1',
'post_translations.excerpt_' . $locale . '^2',
];
$postMultiMatchQuery = new MultiMatchQuery($postSearchFields, $searchTerm);
$postMultiMatchQuery->addParameter('boost', 4);
$postsBoolQuery->add($postMultiMatchQuery, BoolQuery::MUST);
// Publication filters (CORRECTED VERSION)
// From date: must exist AND be in the past (null means NOT published)
$postsBoolQuery->add(
new \ONGR\ElasticsearchDSL\Query\TermLevel\ExistsQuery(
"post_translations.from_{$locale}"
),
BoolQuery::MUST
);
$postsBoolQuery->add(
new \ONGR\ElasticsearchDSL\Query\TermLevel\RangeQuery(
"post_translations.from_{$locale}",
['lte' => $currentTime]
),
BoolQuery::MUST
);
// Till date: (NOT exists) OR (exists AND in future) = never expires OR not yet expired
$tillFilter = new BoolQuery();
// Option 1: field doesn't exist (null)
$tillNotExists = new BoolQuery();
$tillNotExists->add(
new \ONGR\ElasticsearchDSL\Query\TermLevel\ExistsQuery(
"post_translations.till_{$locale}"
),
BoolQuery::MUST_NOT
);
$tillFilter->add($tillNotExists, BoolQuery::SHOULD);
// Option 2: field exists and is in the future
$tillInFuture = new BoolQuery();
$tillInFuture->add(
new \ONGR\ElasticsearchDSL\Query\TermLevel\ExistsQuery(
"post_translations.till_{$locale}"
),
BoolQuery::MUST
);
$tillInFuture->add(
new \ONGR\ElasticsearchDSL\Query\TermLevel\RangeQuery(
"post_translations.till_{$locale}",
['gte' => $currentTime]
),
BoolQuery::MUST
);
$tillFilter->add($tillInFuture, BoolQuery::SHOULD);
$postsBoolQuery->add($tillFilter, BoolQuery::MUST);
// Deleted date: (NOT exists) OR (exists AND in future) = not deleted OR scheduled for future
$deletionFilter = new BoolQuery();
// Option 1: field doesn't exist (null)
$deletionNotExists = new BoolQuery();
$deletionNotExists->add(
new \ONGR\ElasticsearchDSL\Query\TermLevel\ExistsQuery(
"post_translations.deleted_at_{$locale}"
),
BoolQuery::MUST_NOT
);
$deletionFilter->add($deletionNotExists, BoolQuery::SHOULD);
// Option 2: field exists and is in the future
$deletionInFuture = new BoolQuery();
$deletionInFuture->add(
new \ONGR\ElasticsearchDSL\Query\TermLevel\ExistsQuery(
"post_translations.deleted_at_{$locale}"
),
BoolQuery::MUST
);
$deletionInFuture->add(
new \ONGR\ElasticsearchDSL\Query\TermLevel\RangeQuery(
"post_translations.deleted_at_{$locale}",
['gt' => $currentTime]
),
BoolQuery::MUST
);
$deletionFilter->add($deletionInFuture, BoolQuery::SHOULD);
$postsBoolQuery->add($deletionFilter, BoolQuery::MUST);
// Category filter
$categoryIds = timebank_config('main_search_bar.category_ids_posts');
if (!empty($categoryIds)) {
$categoryBoolQuery = new BoolQuery();
foreach ($categoryIds as $categoryId) {
$categoryBoolQuery->add(
new \ONGR\ElasticsearchDSL\Query\TermLevel\TermQuery('category_id', $categoryId),
BoolQuery::SHOULD
);
}
$postsBoolQuery->add($categoryBoolQuery, BoolQuery::MUST);
}
// Execute search
$client = app(Elastic\Elasticsearch\ClientBuilder::class)->build();
$searchBody = ['query' => $postsBoolQuery->toArray()];
echo "Searching for: '{$searchTerm}'" . PHP_EOL;
echo "Locale: {$locale}" . PHP_EOL;
echo "Current time: {$currentTime}" . PHP_EOL;
echo "Category filter: " . json_encode($categoryIds) . PHP_EOL;
echo PHP_EOL;
echo "Query structure:" . PHP_EOL;
echo json_encode($searchBody, JSON_PRETTY_PRINT) . PHP_EOL;
echo PHP_EOL;
try {
$response = $client->search([
'index' => 'posts_index',
'body' => $searchBody
])->asArray();
$totalHits = $response['hits']['total']['value'] ?? 0;
echo "Total hits: {$totalHits}" . PHP_EOL . PHP_EOL;
if (!empty($response['hits']['hits'])) {
echo "Results:" . PHP_EOL;
echo str_repeat('-', 100) . PHP_EOL;
foreach ($response['hits']['hits'] as $hit) {
$postId = $hit['_source']['id'] ?? 'N/A';
$categoryId = $hit['_source']['category_id'] ?? 'N/A';
$title = $hit['_source']['post_translations']['title_en'] ?? 'N/A';
$from = $hit['_source']['post_translations']['from_en'] ?? 'NULL';
$till = $hit['_source']['post_translations']['till_en'] ?? 'NULL';
$score = $hit['_score'] ?? 'N/A';
echo "ID: {$postId} | Cat: {$categoryId} | Score: {$score}" . PHP_EOL;
echo " Title: " . substr($title, 0, 60) . PHP_EOL;
echo " from_en: {$from} | till_en: {$till}" . PHP_EOL;
echo PHP_EOL;
}
}
} catch (\Exception $e) {
echo "Error: " . $e->getMessage() . PHP_EOL;
echo "Stack trace:" . PHP_EOL;
echo $e->getTraceAsString() . PHP_EOL;
}
echo "=== TEST COMPLETE ===" . PHP_EOL;