ЕСТЬ модель Sale, для нее нужно хранить tags для SMART поиска и отображения информации. класс Tags имеет основные свойства id, name, color, type.
ПРЕДЫСТОРИЯ:
viewtopic.php?f=19&t=45265&hilit=tags
Мне было рекомендовано хранить tags в связанной таблице при помощи связи один-ко-многим. Я так и сделал.
МЕТОД ПЕРВЫЙ (КЛАССИЧЕСКИЙ):
1 . создаем Class RealTags хранит именно соответствие записи id основной таблице и id Tags;
Код: Выделить всё
public function getTags()
{
return $this->hasMany(RealTags::className(), ['sale_id' => 'id']);
}
МИНУСЫ: т.к. одной Sale соответствует в среднем 5 tags, то если sale->id = 10.000.000; то realtags->id = 5*10000000.
в итоге записи будут выглядеть так:
Код: Выделить всё
id | sale_id | tag_id
50.000.000 10.000.000 2
50.000.001 10.000.000 6
50.000.002 10.000.000 11
50.000.003 10.000.000 56
50.000.004 10.000.000 99
2. Поиск по Tags
Код: Выделить всё
$query->andWhere([RealTags::tableName() . '.tag_id' => $tags_array]);
$query->groupBy("s.id");
$query->having(new Expression("count(*)=".count($tags_array)));
1. Храним tags, как текстовое поле $sale->tags_id = ",2,6,11,56,99,";
для упаковки и распаковки использовать простые методы
Код: Выделить всё
class Tags extends Activerecord
{ ...
public static function convertToString(array $arr)
{
return ",".implode(",", $arr).",";
}
public static function convertToArray($string)
{
if ($string) return explode(",", preg_replace("/^,|,$/", "", $string));
}
}
2. Поиск:
Код: Выделить всё
foreach ($tags_sale as $tag) {
$query->andWhere(['like', 's.tags_id', "," . $tag . ","]);
}
ПЛЮСЫ:
1.нет минусов первого метода, разница в размерах таблицы Sale c tags_id и без нее 0,2Mб. ( но модели RealTags нет и таблицы Mysql весом 8.5 Mб.)
2. возможно поиск будет гораздо быстрее с elasticsearch.
Ваши комментарии?