MySQL — отдельные хэштеги и текст переполнения стека

Моя база данных

Привет, это пример моей таблицы, я хочу иметь возможность поиска следующим образом: # mat # godis и иметь возможность получить 2 результата с этими тегами (ID 5 и ID 7)

Это мой PHP-код, и он работает при поиске, например, (Globen), (Globen #mat) и (#mat)

//Strip Search
function selectSearch($search){
$lol = preg_replace('/(^|\s)#(\w*[a-zA-Z_]+\w*)/'," ",$search);
$keywords = explode(" ", preg_replace("/\s+/", " ", $lol));
foreach($keywords as $keyword){
$wherelike[] = "name LIKE '%$keyword%'";
}
$search = implode(" and ", $wherelike);
return $search;
}

//Strip tags
function selectTags($tags){
$str = $tags;
$bits = explode(' ', $str);
$newquery = array();

foreach($bits as $bit){
if(strlen($bit) > 0 && $bit[0] === '#') $newquery[] = $bit;
}

$newquery = implode('', $newquery);

$keywords = explode(" ", preg_replace("/\s+/", " ", $newquery));
foreach($keywords as $keyword){
$wherelike[] = "tags LIKE '%".ltrim($keyword,'#')."%'";
}
$tags = implode(" or ", $wherelike);

return $tags;
}

Возвращается (поиск # mat # godis)

select * from stores where name LIKE '%%' and name LIKE '%#godis%' and tags LIKE '%mat#godis%'order by id desc limit 8

Я хочу, чтобы запрос был примерно таким

select * from stores where name LIKE '%%'and tags LIKE '%mat%' and tags LIKE '%godis%' order by id desc limit 8

0

Решение

Этот дизайн действительно плох. Вам нужно использовать таблицу отношений. Проблема в том, если вы пытаетесь найти %#mat%то есть, если есть тег #matheus, это также даст вам результат.

Конечно, есть обходной путь для этой ситуации, но это слишком сложно.

И я не понимаю, что это: name LIKE '%%'

Так что вам нужно, чтобы создать таблицу, как упоминалось ChrisForrence, под названием store_tag как это:

CREATE TABLE IF NOT EXISTS `store_tag` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`tag` varchar(255) NOT NULL COMMENT 'Tag like #mat',
`user_id` int(11) NOT NULL COMMENT 'The foreign ID',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

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

А затем используйте:

SELECT * FROM store_tag, orig_table INNER JOIN origTable ON origTable.id = store_tag.user_id WHERE tag = '#mat' OR tag = '#godis'

(Запрос выше не проверен, это только для примера, и, конечно, вам не нужно SELECT *).

Это вернет вам желаемые результаты.

Намного легче поддерживать ваши данные.

Конечно, перед этим создайте резервную копию из вашей существующей базы данных.

2

Другие решения

Как я уже упоминал в своем комментарии, я бы создал отдельную таблицу для тегов, например:

# The original table. Notice the lack of a 'tags' column
CREATE TABLE `stores` (
`id` INTEGER UNSIGNED AUTO_INCREMENT,
`name` VARCHAR(64) UNIQUE,
PRIMARY KEY(`id`)
);

# A new table, relating stores to tags
CREATE TABLE `store_tags` (
`store_id` INTEGER UNSIGNED,
`label` VARCHAR(64),
PRIMARY KEY(`store_id`, `label`),
FOREIGN KEY(`store_id`) REFERENCES `stores`(`id`) ON DELETE CASCADE
);

Отсюда вы можете использовать вариант следующего запроса, чтобы проверить магазины, соответствующие всем тегам:

SELECT * FROM `stores`
WHERE `id` IN (SELECT `store_id` FROM `store_tags` WHERE `label`='mat')
AND `id` IN (SELECT `store_id` FROM `store_tags` WHERE `label`='godis')
ORDER BY `id` DESC LIMIT 8

Вы можете использовать это, чтобы разделить теги в правильное предложение WHERE вместе с массивом тегов, используемых в качестве входных параметров для вашего запроса PDO

/* Returns an array containing the WHERE clauses, along
* with the tags themselves (used to populate the input parameters for PDO)
*/
function searchTags($in) {
$rQ = '';

// Filter out empty array input elements
$tags = array_filter(explode('#', $in));
if(!count($tags)) {
return false;
}

$first = true;
foreach($tags as $tag) {
$rQ .= ($first ? ' WHERE' : ' AND') . ' `id` IN (SELECT `store_id` FROM `store_tags` WHERE `label`=?)';
if($first) $first = false;
}
return array($rQ, $tags);

}
1

По вопросам рекламы [email protected]