#javascript #php #android #mysql
#javascript #php #Android #mysql
Вопрос:
В моей таблице есть поле keywords, в котором хранятся все ключевые слова, разделенные запятыми. Теперь у меня есть входное слово, и я хочу выполнить поиск по всем элементам из таблицы, соответствующим этому вводу, используя поля ключевых слов в таблице. Есть ли лучший способ сделать это или единственный способ — линейный поиск по всей таблице.
Комментарии:
1. Все, что вам нужно сделать, это выполнить поиск по всем элементам из таблицы, соответствующим этому вводу, используя поля ключевых слов в таблице.
2. поле keywords в моей таблице, в котором хранятся все ключевые слова, разделенные запятыми , нормализуют его
(keyword_group_id, ordinal_position, one_keyword)
.3. @GrumpyCrouton да, я понимаю, но я спрашивал, есть ли другой способ
4. @Akina не могли бы вы подробнее рассказать, пожалуйста. Используя пример, если это возможно
5. @dhruvtailor Откуда нам знать? Вам необходимо предоставить более подробную информацию. Разбейте структуру соответствующих таблиц, предоставьте нам примеры данных, примеры поиска, пример ожидаемых результатов
Ответ №1:
Пример.
Теперь у вас есть хранилище, которое выглядит как:
group_id | keywords
-----------------------------------------
... | ...
123 | word1,word2,word3
124 | word5,word2
125 | word3,word4,word1,word7,word8
... | ...
Вы преобразуете его в
group_id | ordinal | keyword
----------------------------
... ... ...
123 1 word1
123 2 word2
123 3 word3
124 1 word5
124 2 word2
125 1 word3
125 2 word4
125 3 word1
125 4 word7
125 5 word8
... ... ...
Когда вам нужен идентификатор группы для групп, который содержит, например, 'word2'
, вы выполняете
SELECT group_id
FROM keywords
WHERE keyword = 'word2'
который вернет
group_id
--------
123
124
И когда вам нужны целые группы ключевых слов, которые вы выполняете
SELECT group_id, GROUP_CONCAT(group_id ORDER BY ordinal) keywords
FROM keywords
JOIN ( SELECT group_id
FROM keywords
WHERE keyword = 'word2' ) AS groups USING (group_id)
который вернет
group_id | keywords
-------------------------------
123 | word1,word2,word3
124 | word5,word2
Чтобы повысить производительность, вы бы создали соответствующие индексы ( (keyword, group_id)
постепенно (group_id)
) в структуре таблицы.
Комментарии:
1. У меня был бы соблазн переместить вашу структуру ссылок в формат «многие ко многим», где вы можете хранить исходный идентификатор таблицы, порядковую позицию и идентификатор слова (PK для обоих идентификаторов). Тогда ваша таблица word может иметь уникальный индекс для слова, что ускорит поиск.
2. @Skrrp Это верно, если ключевое слово синхронизировано для всех групп, в которых оно упоминается (изменение в одной группе должно изменить его во всех других группах), в противном случае приведенная выше структура более безопасна.
3. ах, я понимаю, откуда вы. Я бы лично рассматривал слова как неизменяемые и не «принадлежащие» ни к одной из записей в левой таблице. Поэтому, если кто-то «удаляет» слово, оно удаляет m2m. Если слово «отредактировано», то m2m удаляется и создается заново для нового слова (независимо от того, было ли оно вставлено или уже есть).
Ответ №2:
Я собираюсь рекомендовать использовать выделенный поисковый индекс. Ответ Акины отлично подходит для выполнения этого полностью внутри MySQL. Если вы хотите сопоставить Dave
like '%ave%'
, вам нужно ознакомиться с FULLTEXT
индексами; Руководство по MySQL.
Однако с помощью этой структуры вы только что создали половину поискового индекса. Для вас было бы лучше ввести реальный индекс поиска в свой стек. В наши дни Elastic действительно легко реализовать с помощью библиотек для Laravel и Symfony или просто с помощью драйвера PHP (требуется некоторая сборка). Как только у вас будет индекс поиска, он предоставит дополнительные преимущества, такие как автоматическое множественное число поисковых запросов, и даже вернет ваши результаты, упорядоченные по количеству совпадений.
Все, что вам нужно сделать, это создать индекс поиска, содержащий одно поле и пробел — разделите все ваши слова в нем для каждой записи в вашей базе данных MySQL. Тогда ваша эластичная запись будет выглядеть следующим образом:
{
"_id": "[Elastic's record ID]",
"mysql_id": "[Your ID in MySQL]",
"search_field": "word1 word2 word3"
}
Поиск по этому индексу вернет вам идентификаторы MySQL для поиска, которые затем вы можете использовать обратно в своем PHP-приложении.