Организация поиска в каталоге PHP

Раздел: Разработка веб-приложений -> Поиск в PHP

Различные подходы к поиску в каталоге

Как организовать быстрый полнотекстовый поиск по каталогу товаров в MySQL?

Наиболее эффективное решение для поиска по текстовым полям (название, описание) - это использование полнотекстового индекса MySQL (FULLTEXT). Оно обеспечивает высокую скорость, релевантность и поддержку различных режимов (естественный язык, булевый).

Для начала добавляем полнотекстовый индекс на нужные столбцы:


CREATE FULLTEXT INDEX ft_index ON products (name, description);
  

Search index php topic (поиск темы в индексе php)

Затем выполняем запрос с использованием MATCH ... AGAINST. Пример на PHP с подготовленным выражением:


<?php
$searchTerm = 'ноутбук'; // предположим, получено от пользователя
$stmt = $pdo->prepare(
    "SELECT id, name, price,
            MATCH(name, description) AGAINST(:term IN BOOLEAN MODE) AS relevance
     FROM products
     WHERE MATCH(name, description) AGAINST(:term IN BOOLEAN MODE)
     ORDER BY relevance DESC"
);
$stmt->execute(['term' => $searchTerm]);
$results = $stmt->fetchAll();
?>
  

Search php images (поиск изображений в php)

Проблема: при использовании FULLTEXT минимальная длина слова (по умолчанию 4 символа) может игнорировать короткие запросы. Решение - изменить параметр ft_min_word_len в конфигурации MySQL и перестроить индекс.

Другая частая ошибка - забыть про экранирование специальных символов в булевом режиме (+, -, *, " и т.д.). Рекомендуется предварительно очищать запрос или использовать режим естественного языка.

Как выполнить простой поиск по каталогу с использованием SQL LIKE?

Если полнотекстовый индекс недоступен или база данных небольшая, можно использовать оператор LIKE. Однако этот вариант медленный на больших объёмах и не поддерживает ранжирование по релевантности.


<?php
$searchTerm = '%' . $search . '%';
$stmt = $pdo->prepare("SELECT * FROM products WHERE name LIKE :term");
$stmt->execute(['term' => $searchTerm]);
$results = $stmt->fetchAll();
?>
  

Posts php search (поиск постов в php)

Проблемы: оператор LIKE с ведущим '%' не использует индексы, что приводит к полному сканированию таблицы. Также возможна SQL-инъекция, если не использовать подготовленные выражения.

Как организовать поиск по каталогу без базы данных, используя массив?

Для статических данных или тестирования можно выполнять поиск прямо в PHP через array_filter, in_array или array_search. Этот вариант подходит только для очень маленьких наборов данных (десятки-сотни элементов).


<?php
$products = [
    ['id' => 1, 'name' => 'Ноутбук ASUS'],
    ['id' => 2, 'name' => 'Монитор Dell'],
    ['id' => 3, 'name' => 'Клавиатура']
];
$search = 'ноут';
$filtered = array_filter($products, function($item) use ($search) {
    return stripos($item['name'], $search) !== false;
});
?>
  

Forum index php search (поиск на форуме (index) в php)

Проблема: потребление памяти и низкая производительность при больших массивах. Также нет возможности использовать полнотекстовый поиск, пагинация неэффективна.

Как подключить внешний поисковый движок Elasticsearch для каталога?

Для высоконагруженных проектов с большим объёмом данных и сложными поисковыми запросами (нечёткий поиск, автодополнение, фильтры) целесообразно использовать Elasticsearch. В PHP для работы с ним применяется официальный клиент elastic/elasticsearch.


<?php
require 'vendor/autoload.php';
use Elastic\Elasticsearch\ClientBuilder;

$client = ClientBuilder::create()->setHosts(['localhost:9200'])->build();

$params = [
    'index' => 'products',
    'body'  => [
        'query' => [
            'multi_match' => [
                'query' => 'ноутбук',
                'fields' => ['name^3', 'description']
            ]
        ]
    ]
];
$response = $client->search($params);
$results = $response['hits']['hits'];
?>
  

Сложность: необходимо развернуть и поддерживать Elasticsearch отдельно, синхронизировать данные между MySQL и ES. Возможны проблемы с анализом русского языка, требуется установка соответствующего анализатора (например, elasticsearch-analysis-morphology).

- Search php keywords (поиск по ключевым словам в php)
- Search php mode search (режим поиска php)
- Search php browse (просмотр поиска php)

Расширенные примеры и результаты

Пример 1: полнотекстовый поиск с булевыми операторами

Использование булевого режима для поиска точных фраз, исключений и обязательных слов.

Пример

<?php
$query = '+ноутбук -lenovo "игровой"';
$stmt = $pdo->prepare("SELECT name, MATCH(name, description) AGAINST(:q IN BOOLEAN MODE) AS rel
                       FROM products
                       WHERE MATCH(name, description) AGAINST(:q IN BOOLEAN MODE)");
$stmt->execute(['q' => $query]);
foreach ($stmt as $row) {
    echo $row['name'] . ' (релевантность: ' . $row['rel'] . ')<br>';
}
?>
Результат (пример):
Ноутбук ASUS TUF Gaming (релевантность: 5.2)
Ноутбук MSI GF75 (релевантность: 3.8)

Пример 2: поиск по массиву с несколькими полями и сортировкой

Пример

<?php
$products = [
    ['id' => 1, 'name' => 'Ноутбук Apple MacBook Pro', 'price' => 150000],
    ['id' => 2, 'name' => 'Ноутбук Lenovo ThinkPad', 'price' => 80000],
    ['id' => 3, 'name' => 'Монитор LG 27"', 'price' => 30000]
];

$search = 'ноутбук';
$results = array_filter($products, function($p) use ($search) {
    return stripos($p['name'], $search) !== false;
});

usort($results, function($a, $b) {
    return $b['price'] <=> $a['price']; // сортировка по убыванию цены
});

print_r($results);
?>
Array
(
    [0] => Array ([id] => 1, [name] => Ноутбук Apple MacBook Pro, [price] => 150000)
    [1] => Array ([id] => 2, [name] => Ноутбук Lenovo ThinkPad, [price] => 80000)
)

Пример 3: поиск с использованием Elasticsearch и пагинацией

Пример

<?php
$page = 1;
$perPage = 10;
$from = ($page - 1) * $perPage;

$params = [
    'index' => 'products',
    'from'  => $from,
    'size'  => $perPage,
    'body'  => [
        'query' => ['match' => ['name' => 'ноутбук']],
        'sort'  => ['price' => ['order' => 'desc']]
    ]
];
$response = $client->search($params);
echo 'Найдено всего: ' . $response['hits']['total']['value'] . '<br>';
foreach ($response['hits']['hits'] as $hit) {
    echo $hit['_source']['name'] . ' - ' . $hit['_source']['price'] . '<br>';
}
?>
Найдено всего: 23
Ноутбук ASUS ROG Strix - 120000
Ноутбук Dell XPS - 110000
... (10 записей на странице)

Пример 4: обработка ошибок при использовании FULLTEXT

Типичная ошибка: пустой запрос или использование стоп-слов. Оборачиваем в try-catch.

Пример

<?php
try {
    $stmt = $pdo->prepare($sql);
    $stmt->execute(['q' => $query]);
} catch (PDOException $e) {
    if (strpos($e->getMessage(), 'FTS') !== false) {
        // логируем, показываем пользователю общее сообщение
        echo 'Поиск временно недоступен';
    }
}
?>

Поиск по каталогу в PHP - comments

En
Catalogue php search (php)