Упорядочить по количеству вхождений LIKE Laravel Php

В настоящее время у меня есть простая поисковая система на моем сайте

Я пытаюсь соответствовать keyword во всех областях.

Вот упрощенные рабочие коды

$keyword_search = "Hello World";
$delimeter = ' '; //or your separator
$keywords = explode($delimeter, $keyword_search); 

$base_query = \App\Models\EntireSearchSite::where('id','!=',NULL);

foreach($keywords as $keyword){
    $base_query->where(function($query) use ($keyword){
            $query->where('part_number', 'like', '%' . $keyword . '%') 
                ->orWhere('part_name', 'like', '%' . $keyword . '%')
                ->orWhere('category', 'like', '%' . $keyword . '%')
                ->orWhere('description', 'like', '%' . $keyword . '%');
    });
    
}

$data = $base_query->paginate(20);
return $data;

Что я пытаюсь сделать, так это сопоставить все ключевые слова, подсчитать все совпадающие ключевые слова (для каждого вхождения) и выполнить Order By Desc от самых высоких вхождений к самым низким.

Если я войду "Hello World"

он найдет все данные, которые будут соответствовать "Hello World"

У меня есть part_number, part_name, category, description поля

он суммирует общее количество вхождений во всех полях и упорядочивает ORDER BY от самого высокого до самого низкого (DESC)

ПРИМЕР:

ДАННЫЕ №1

количество совпадающих ключевых слов в part_number равно 0

количество совпадающих ключевых слов в part_name равно 2

количество совпадающих ключевых слов в category равно 0

количество совпадающих ключевых слов в description равно 0

ВСЕГО = 2

ДАННЫЕ #2

количество совпадающих ключевых слов в part_number равно 0

количество совпадающих ключевых слов в part_name равно 0

количество совпадающих ключевых слов в category равно 2

количество совпадающих ключевых слов в description равно 10

ВСЕГО = 12

ДАННЫЕ №3

количество совпадающих ключевых слов в part_number равно 0

количество совпадающих ключевых слов в part_name равно 0

количество совпадающих ключевых слов в category равно 0

количество совпадающих ключевых слов в description равно 5

ВСЕГО = 5

и порядок по описанию должен быть примерно таким

ДАННЫЕ №2

ДАННЫЕ №3

ДАННЫЕ №1

ОБНОВЛЯТЬ*

Пробовал ответ от @Anas

$delimeter = ' '; //or your separator
$keywords = explode($delimeter, $keyword_search); 

$base_query = \App\Models\EntireSearchSite::where('id','!=',NULL);

foreach($keywords as $keyword){
    $base_query->where(function($query) use ($keyword){
            $query->where('part_number', 'like', '%' . $keyword . '%') 
                ->orWhere('part_name', 'like', '%' . $keyword . '%')
                ->orWhere('category', 'like', '%' . $keyword . '%')
                ->orWhere('description', 'like', '%' . $keyword . '%');
    });
}

foreach($keywords as $keyword){
            $base_query->selectRaw(function($querySelect) use ($keyword){
                $querySelect->selectRaw('
                    Round ((Char_length(Concat(
                        part_number, 
                        part_name,
                        category,
                        description

                    )) - Char_length(REPLACE ( Concat(
                        part_number, 
                        part_name,
                        category,
                        description
                    ), "'.$keyword.'", ""))) / Char_length("'.$keyword.'"))  AS count 
                ');

            });
}        

$data = $base_query->orderBy('count','DESC')->paginate(20);
return $data;

Но я получаю неопределенное количество столбцов

Обновлять

Прикладной ответ @Donkarnash

Не совсем то, что вы ищете, но посмотрите на соответствие: w3resource.com/mysql/mysql-full-text-search-functions.php

Sindhara 12.12.2020 00:45

я обновил свой вопрос

Pablo 12.12.2020 00:56
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
2
2
883
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Попробуйте объединить связанный столбец в одну строку, а затем получите общее количество вхождений по этому образцу запроса. также вы можете использовать в select DB:raw() Документация Laravel

SELECT email, 
       name, 
       Round ((Char_length(Concat(email, name)) - Char_length(REPLACE ( Concat(email,name), "anas", ""))) / Char_length("anas")) AS count 
FROM   users
Having count >0 
ORDER  BY count DESC; 

Результат запроса

Для отдельного ключевого слова вы можете суммировать новую функцию раунда с другим ключевым словом, проверьте этот запрос.

SELECT email, 
       name, 
       Round ((Char_length(Concat(email, name)) - Char_length(REPLACE ( Concat(email,name), "first_keyword", ""))) / Char_length("first_keyword")) 
       + Round ((Char_length(Concat(email, name)) - Char_length(REPLACE ( Concat(email,name), "second_keyword", ""))) / Char_length("second_keyword"))  AS count 
FROM   users
Having count >0 
ORDER  BY count DESC; 

Чтобы сделать его нечувствительным к регистру, вы можете преобразовать ключевые слова и столбцы в нижний регистр. Бывший:

 SELECT email,
        name,
    Round ((lower(Char_length(Concat(email, name))) - Char_length(REPLACE ( lower(Concat(email,name)), lower("aasd"), ""))) / Char_length(lower("aasd"))) AS count 
    FROM   users 
    Having count >0 ORDER  BY count DESC;

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

Pablo 26.12.2020 05:41

Я думаю, что я довольно близок, я могу получить данные подсчета на основе вашего кода. Но у меня есть это дополнительное поле, называемое page_content типом данных TEXT, где оно содержит некоторый HTML-код. например <p> Lorem sum</p> <h3>Lorem Sum</h3>, когда я пытался добавить это поле в запрос, запрос, похоже, не работает

Pablo 29.12.2020 00:17

В чем ошибка при использовании поля page_content

anas omush 29.12.2020 04:15

он не возвращает никаких данных при добавлении поля page_content. это поле иногда содержит некоторое значение html, иногда просто null. возможно, потому что некоторые записи являются нулевыми или, может быть, потому, что он не может подсчитать значение поля, если значение содержит html-коды.

Pablo 04.01.2021 06:03

Поскольку в цикле используется selectRaw, псевдоним операции подсчета не должен быть count (повторяется для всех итераций цикла). Скорее это должно быть 'count'.$keyword, чтобы сделать его уникальным псевдонимом.

Точно так же orderBy() также должен быть определен в цикле, чтобы упорядочивать столбцы 'count'.$keyword.

$base_query = \App\Models\EntireSearchSite::where('id','!=',NULL);

foreach($keywords as $keyword){
    $base_query->where(function($query) use ($keyword){
        $query->where('part_number', 'like', '%' . $keyword . '%') 
            ->orWhere('part_name', 'like', '%' . $keyword . '%')
            ->orWhere('category', 'like', '%' . $keyword . '%')
            ->orWhere('description', 'like', '%' . $keyword . '%');
    });
}

foreach($keywords as $keyword) {
    $base_query->selectRaw('
        Round (
            (Char_length(Concat(email, name)) - Char_length(REPLACE ( Concat(email,name), "' . $keyword .'", ""))
        ) / Char_length("' . $keyword .'")
        ) AS count' .  $keyword
    )
    ->orderBy("count$keyword", "desc");
}

$data = $base_query->paginate(20);
return $data;

Привет, пытался сделать это, но получил Object of class Closure could not be converted to string это из-за типа данных моих полей?

Pablo 18.12.2020 07:03

Можете ли вы найти в трассировке стека, какая строка кода вызывает ошибку. Потому что я пробовал в соответствии с примером таблицы пользователей @anas, и он безупречно работает с двумя ключевыми словами.

Donkarnash 18.12.2020 07:06

Вероятно, в лог-файле по адресу sotrage/logs/laravel.log будет подробная запись.

Donkarnash 18.12.2020 07:11

Я обновил свой пост, чтобы увидеть ошибку, у меня есть 10 оставшихся полей, которые я не включил здесь в коды, только part_number, part_name, категория, описание. это необходимо?

Pablo 18.12.2020 07:12

проверим это

Pablo 18.12.2020 07:12

Обновили ответ, думаю, внешний selectRaw вызывал ошибку во втором цикле foreach - попробуйте обновленный

Donkarnash 18.12.2020 07:23

Просто для информации, вы можете использовать полнотекстовый поиск и получить оценку в виде процента совпадения - если это служит вашей цели.

Donkarnash 18.12.2020 07:34

@RaeIan «У меня есть 10 оставшихся полей, которые я не включил сюда в коды» - каждый поиск типа «%$term%» снижает производительность, поскольку он не может использовать какой-либо индекс - будьте осторожны. Если у вас есть несколько столбцов для поиска, используя подобную нормализацию оператора в качестве помощи виртуальных столбцов или, что еще лучше, было бы определить полный поисковый индекс с несколькими столбцами в таблице.

Donkarnash 18.12.2020 10:08

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

foreach($i=0;$i<count($data);$i++){
 foreach($keywords as $keyword)
 {
   if (strpos($data[$i]->partition, $keyword) !== false) {
    $counter = $counter+1; 
  .
  .
  .
  .

  }
 }
  $final[$i] = [
  'data'=>$data[$i],
  'priority'=>$counter
];
}
then you can sort it by ```arsort()``` based on priority

Другие вопросы по теме