- en
- ru
This is an old revision of the document!
Table of Contents
Trade CMS
Thumb CMS - это следующий шаг в развитии SmartCJ.
Мы всегда старались поддерживать все возможные конфигурации серверов, включая те, которые работали на PHP 4 и MySQL 3.23, несмотря на то, что поддержка этих версий прекращена десять лет назад. Сейчас время сделать следующий шаг во многих отношениях.
What's new
В новой ветке есть ряд качественных изменений для всех сторон скрипта.
- Была произведена оптимизация базы, дабы сделать возможным быструю работу баз по с 200-300к тумб в каждой категории. Ранее это была проблема, что группы с большим кол-вом тумб серьезно замедляли работу сайта.
- Кроны можно запускать как угодно часто, это будет влиять только на скорость обновления статистики и сохранениях хистори. При этом кроны контролируют запуск себя дабы не запускались дубли. Однако в связи с пунктом 1 это воможно не понадобится.
- Оптимизированы выборки и апдейты базы
Скрипт стал полностью “незаметным”:
- Вы можете ставить скрипт в любую папку
- Реврайты упрощены, можно делать любые линки на сайте
- Скрипт не ставит никаких кук в режиме Cookie Engine = Cache либо ставит закодированные в режиме Cookie Engine = MD5
- Можно убирать TCMS Rotation Parameter и скрипт все равно сможет считать статистику тумб, даже если их несколько на галеру + Cell K
Таким образом вопрос о ранжировании сайтов гуглом в зависимости от скрипта будет полностью снят.
Добавлен ряд уникальных фич:
- Thumb Split - уникализация тумб путем разрезания их на несколько частей
- FaceDetect - автоматизация нарезки тумб, с учетом положения лица для того что бы создавать тумбы более качественно на автомате
Installation
Установка стала еще проще и должна понравиться админам. Сейчас можно ничего не скачивать, а достаточно в шеле дать комманду
curl -sS http://smartcj.com/updates2/install | php --
и скрипт будет установлен в интерактивном режиме. PS да, два тире в конце обязательны
так же можно указать все параметры прямо в коммандной строке
curl -sS http://smartcj.com/updates2/install | php -- mysql_host= mysql_user= mysql_pass= mysql_name= scj_folder= domain= admin_email=
Default Rewrites
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]{2})/(.*)$ $2?force_lng=$1&%{QUERY_STRING} [L]
# add &dont_count_in_trade=true if you dont want to count these clicks
RewriteRule ^category/([^/]+)/$ /script_folder_name/cgi/out.php?url=content&p=100&skip_sell=true&group_name=$1&order=ctr&%{QUERY_STRING} [L]
RewriteRule ^category/([^/]+)/([^/]+)/([^/]+)/$ /script_folder_name/cgi/out.php?url=content&p=100&skip_sell=true&group_name=$1&order=$2&page=$3&%{QUERY_STRING} [L]
#slug galleries
RewriteRule ^gallery/([^/]+)/index.html$ /script_folder_name/cgi/out.php?url=content&slug=$1&%{QUERY_STRING} [L]
RewriteRule ^gallery/([^/]+)/([0-9]{1,2}).html$ /script_folder_name/cgi/out.php?url=content&slug=$1&item_id=$2&%{QUERY_STRING} [L]
#tags
RewriteRule ^tag/([^/]+)/([^/]+)/([^/]+)/$ /script_folder_name/cgi/out.php?url=content&p=100&skip_sell=true&tag=$1&page=$3&order=$2&%{QUERY_STRING} [L]
RewriteRule ^tag/([^/]+)/([^/]+)/$ /script_folder_name/cgi/out.php?url=content&p=100&skip_sell=true&tag=$1&page=$2&%{QUERY_STRING} [L]
RewriteRule ^tag/([^/]+)/$ /script_folder_name/cgi/out.php?url=content&p=100&skip_sell=true&tag=$1&%{QUERY_STRING} [L]
#model galleries
RewriteRule ^model_galleries/([^/]+)/$ /?model_slug=$1&force_template=model_galleries [L]
RewriteRule ^model_galleries/([^/]+)/([^/]+)/$ /?model_slug=$1&page=$2&force_template=model_galleries [L]
RewriteRule ^model/([^/]+)/$ /?model_slug=$1&force_template=model_galleries&%{QUERY_STRING} [L]
RewriteRule ^model/([^/]+)/([^/]+)/([^/]+)/$ /?model_slug=$1&force_template=model_galleries&order=$2&page=$3&%{QUERY_STRING} [L]
RewriteRule ^search/([^/]+)/([^/]+)/$ /?search=$1&page=$2&%{QUERY_STRING}
RewriteRule ^search/([^/]+)/([^/]+)/([^/]+)/$ /?search=$1&order=$2&page=$3&%{QUERY_STRING}
Для nginx
server {
....
location /scj/scj2.lic {
return 404;
}
location / {
.....
if (!-e $request_filename) {
rewrite "^/([^/]{2})/(.*)$" /$2?force_lng=$1&$query_string ;
}
}
location /gallery {
rewrite ^/gallery/([^/]+)/index.html$ /script_folder_name/cgi/out.php?url=content&slug=$1&$query_string ;
rewrite "^/gallery/([^/]+)/([0-9]{1,2}).html$" /script_folder_name/cgi/out.php?url=content&slug=$1&item_id=$2&$query_string ;
}
location /category {
rewrite ^/category/([^/]+)/$ /script_folder_name/cgi/out.php?url=content&p=100&dont_count_in_trade=true&skip_sell=true&group_name=$1&order=ctr&$query_string ;
rewrite ^/category/([^/]+)/([^/]+)/([^/]+)/$ /script_folder_name/cgi/out.php?url=content&p=100&dont_count_in_trade=true&skip_sell=true&group_name=$1&order=$2&page=$3&$query_string ;
}
location /tag {
rewrite ^/tag/([^/]+)/([^/]+)/([^/]+)/$ /script_folder_name/tube/index.php?tag=$1&page=$3&order=$2&$query_string ;
rewrite ^/tag/([^/]+)/([^/]+)/$ /script_folder_name/tube/index.php?tag=$1&page=$2&$query_string ;
rewrite ^/tag/([^/]+)/$ /script_folder_name/tube/index.php?tag=$1&$query_string ;
}
location /model_galleries {
rewrite ^/model_galleries/([^/]+)/$ /script_folder_name/tube/?model_slug=$1&force_template=model_galleries ;
rewrite ^/model_galleries/([^/]+)/([^/]+)/$ /script_folder_name/tube/?model_slug=$1&page=$2&force_template=model_galleries ;
}
location /model {
rewrite ^/model/([^/]+)/$ /script_folder_name/tube/?model_slug=$1&force_template=model_galleries&$query_string ;
rewrite ^/model/([^/]+)/([^/]+)/([^/]+)/$ /script_folder_name/tube/?model_slug=$1&force_template=model_galleries&order=$2&page=$3&$query_string ;
}
location /search {
rewrite ^/search/([^/]+)/([^/]+)/$ /script_folder_name/tube/index.php?search=$1&page=$2&$query_string;
rewrite ^/search/([^/]+)/([^/]+)/([^/]+)/$ /script_folder_name/tube/index.php?search=$1&order=$2&page=$3&$query_string;
}
Search
По дефолту для поиска используется конструкция примерно WHERE description LIKE '%search_term%'. В настройках ротации есть пункт
Search fields If you don't use Sphinx the script will use Mysql built-in functionality. It's slower so we limit amount of fields Please, read the last WIKI about the last option.
По дефолту скрипт ищет по в description, в этом пункте можно настроить поиск в Title (Alt), либо по обоим полям сразу, что конечно создает несколько больше нагрузки.
Лучший вариант - это настройка Sphinx о чем рассказано ниже.
Но есть компромисный вариант: FullText Search для Mysql (последний из пунктов опции Search fields). Его смысл в том, что Mysql так же умеет искать учитывая морфологию, однако до версии 5.6 он это делал только для таблиц MyISAM.
Итого если вы хотите использовать этот вариант, который несоклько проще варианта Sphinx в настройке надо для таблиц rot_gallery_data* добавить индекс
ALTER TABLE `rot_gallery_data1` ADD FULLTEXT ( `alt` , `description` )
И переключить в настройках опцию на поиск FullText.
Sphinx Config
Обратите внимание, что в Sphinx Settings в 99% случае надо писать 127.0.0.1
Пример конфига
Надо внести изменения в секцию
searchd
{
listen = your_port:mysql41
основное тут - добавление mysql41, новый вариант для сфинкс слушать по протоколу mysql
Далее пример для базы
source your_name_source
{
type = mysql
sql_host = localhost
sql_user =
sql_pass =
sql_db =
sql_port = 3306 # optional, default is 3306
sql_query_pre = SET NAMES utf8
sql_query = SELECT gi.gallery_id, UNIX_TIMESTAMP(gi.activation_date) as date, alt, description, gi.duration, sponsor_id, gs.total_ctr, gi.content_type, \
(SELECT group_concat(tag_name) FROM rot_gal2tag g2t \
LEFT JOIN rot_tags as t on t.tag_id = g2t.tag_id \
WHERE g2t.gallery_id = gi.gallery_id) as tags, \
(SELECT group_concat(tag_id) FROM rot_gal2tag g2t \
WHERE g2t.gallery_id = gi.gallery_id) as tag_ids, \
(SELECT group_concat(name) FROM rot_groups \
WHERE rot_groups.id in (SELECT group_id FROM rot_gallery_stats1 WHERE rot_gallery_stats1.gallery_id = gi.gallery_id AND group_id != 0) ) as group_names, \
\
(SELECT group_concat(name) FROM rot_groups \
WHERE rot_groups.id in (SELECT group_id FROM rot_gallery_stats1 WHERE rot_gallery_stats1.gallery_id = gi.gallery_id AND group_id != 0) ) as group_names, \
(SELECT group_concat(gss.group_id) FROM rot_gallery_stats1 as gss \
WHERE gss.gallery_id = gi.gallery_id AND group_id != 0) as categories \
FROM rot_gallery_info AS gi \
JOIN rot_gallery_data1 AS gd ON gi.gallery_id = gd.gallery_id \
JOIN rot_gallery_stats1 AS gs ON gs.gallery_id = gi.gallery_id \
WHERE gallery_status = 'active' and gallery_type = 0 \
and gs.best_thumb = 'yes' and gs.group_id = 0 AND gs.group_id NOT IN (SELECT group_id FROM rot_groups_data WHERE status != 1)
sql_attr_timestamp = date
sql_attr_uint = duration
sql_attr_uint = sponsor_id
sql_attr_float = total_ctr
sql_attr_uint = content_type
sql_attr_multi = uint categories from field;
sql_attr_multi = uint tag_ids from field;
}
index your_name_index
{
source = your_name_source
path = /your_path
docinfo = extern
morphology = stem_en
charset_type = utf-8
}
Sphinx Delta Config
При создании индекса sphinx делает индекс текущего состояния базы и если после индексирования в базе были какие-либо изменения, то sphinx не найдет новых данных, тк они были добавлены после индексирования.
Логический вывод из этого: надо проводить реиндексацию после каждого изменения в базе, однако проблема в том, что если база достаточно большая то индексация может занимать длительное время. И индексация это затратный по ресурсам процесс.
Что бы решить эту проблему придумали delta index – это индекс в который попадут измения, которые произошли с момента полной индексации и до момента создания дельта индекса. При этом, поскольку индексируется малое кол-во данных, операция проходит очень быстро.
При поиска sphinx будет искать и в основном индексе и в дельта индексе, и таким образом будет видеть все измения. Создание дельта индекса можно поставить как угодно часто.
Итого :
в основную часть, которая у вас уже есть надо добавить после
sql_query_pre = SET NAMES utf8
строку
sql_query_pre = UPDATE rot_settings SET value = (SELECT MAX(gallery_id) FROM rot_gallery_info) WHERE name = 'sphinx_max_gallery_id'
Теперь надо добавить создание дельта индекса
source delta : your_name_source
{
sql_query_pre = SET NAMES utf8
sql_query = SELECT gi.gallery_id, UNIX_TIMESTAMP(gi.activation_date) as date, \
\
gd.alt, gd.description, gi.duration, gi.sponsor_id, gs.total_ctr, gi.content_type, rot_sponsors.sponsor_name, rot_sponsors.sponsor_site,\
\
\
(SELECT group_concat(tag_id) FROM rot_gal2tag g2t \
WHERE g2t.gallery_id = gi.gallery_id) as tag_ids, \
\
# TAGS START you can remove this part up to TAG END \
# this part indexes tags, if you remove it - tags wont be indexed \
# ligther index = less memory usage and faster search \
(SELECT group_concat(tag_name) FROM rot_gal2tag g2t \
LEFT JOIN rot_tags as t on t.tag_id = g2t.tag_id \
WHERE g2t.gallery_id = gi.gallery_id) as tags, \
\
# TAGS END \
\
\
# GROUP START you can remove this part up to TAG END \
# this part indexes group names, if you remove it - it wont be indexed \
# ligther index = less memory usage and faster search \
(SELECT group_concat(name) FROM rot_groups \
WHERE rot_groups.id in (SELECT group_id FROM rot_gallery_stats1 \
WHERE rot_gallery_stats1.gallery_id = gi.gallery_id AND group_id != 0) \
) as group_names, \
\
\
# GROUP END \
\
# Models START you can remove this part up to MODEL END \
# this part indexes model names, if you remove it - it wont be indexed \
# ligther index = less memory usage and faster search \
(SELECT group_concat(model_name) FROM rot_models \
WHERE rot_models.model_id in (SELECT model_id FROM rot_gal2model \
WHERE rot_gal2model.gallery_id = gi.gallery_id) \
) as model_names, \
\
# MODEL END \
\
\
(SELECT group_concat(distinct(gss.group_id)) FROM rot_gallery_stats1 as gss \
WHERE gss.gallery_id = gi.gallery_id AND group_id != 0) as categories \
\
FROM rot_gallery_info AS gi \
JOIN rot_sponsors on rot_sponsors.sponsor_id = gi.sponsor_id \
JOIN rot_gallery_data1 AS gd ON gi.gallery_id = gd.gallery_id \
\
\
JOIN rot_gallery_stats1 AS gs ON gs.gallery_id = gi.gallery_id \
WHERE gallery_status = 'active' and gallery_type = 0 \
and gs.best_thumb = 'yes' and gs.group_id = 0 \
AND gs.group_id NOT IN (SELECT group_id FROM rot_groups_data WHERE status != 1) and gi.gallery_id > ( SELECT value FROM rot_settings WHERE name = 'sphinx_max_gallery_id' )
}
index delta : your_name_index
{
source = delta
path = /your_full_path/data/delta
}
Как можно заметить запрос такой же, отличается только наличием в выборке по sphinx_max_gallery_id.
После этого надо доабвить в крон индексацию новых записей так часто, как вам нравится строкой
indexer --rotate delta
После создания индекса надо прописать delta в Sphinx Delta Index настройках ротации.
и раз в сутки например можно присоединять дельта индекс к основному
indexer --rotate --merge your_name_index delta
Все.
