cyrax_02 08 августа 2015 2 23
Классическая схема физического хранения изображений галереи — набор папок для каждого ресурса, внутри — графические файлы. Для отображения на сайте изображений некоторого ресурса просто-напросто берём графические файлы из папки, соответствующей нашему ресурсу. Просто и логично.

Но в моём случае:
а) каждый графический файл может быть связан с одним и более ресурсами одновременно (а в некоторые моменты времени может быть не связан ни с одним из ресурсов)
б) каждый графический файл имеет с десяток характеристик (по которым будет выполняться сортировка/фильтрация)
в) каждый графический файл будет иметь комментарии пользователей
г) каждый графический файл будет иметь свою собственную страницу на сайте (с описанием, характеристиками, комментариями и пр.)

Очевидно, что простым хранением графических файлов в тех или иных папках здесь не обойтись — нужно ещё хранить данные о каждом изображении. Возможны 2 варианта:

ВАРИАНТ 1. Для каждого графического файла создаётся отдельный ресурс (типа «Документ» или «Статический ресурс») с TV-параметрами

Преимущества:
1.Обслуживание, управление и формирование характеристик изображений выполняется стандартными средствами modx (характеристики, вычисляемые автоматически путём анализа изображения, легко реализуются на уровне плагинов)
2.Загрузка страниц, посвящённых изображениям, будет выполняться без каких-либо проблем стандартными средствами modx (как и страницы любых других ресурсов)
3.Легко прикрутить готовые компоненты для работы с комментариями (при хранении в собственных таблицах придётся писать свою систему комментариев)
4.Число просмотров, число комментариев и прочие realtime-характеристики будут обрабатываться теми же средствами, которые работают в отношении прочих ресурсов

Недостатки:
1.Быстрее себя проявит проблема большой карты ресурсов
2.Чуть медленнее будет выполняться фильтрация и сортировка по TV этих изображений. Впрочем это проблема/особенность архитектуры modx (а вернее, т.н. универсальных БД), а никак не проблема выбранного варианта хранения данных изображений

ВАРИАНТ 2. Информация о каждом изображении хранится в отдельной таблице

Преимущества:
1. Проблема большой карты ресурсов будет проявляться в существенно меньшей степени
2. Чуть быстрее будет работать фильтрация и сортировка по характеристикам изображений

Недостатки:
1.Интерфейс для формирования и просмотра характеристик изображений придётся разрабатывать свой
2.Систему комментариев придётся разрабатывать свою
3.Существенно урезаются стандартные возможности modx по работе с изображениями на уровне чанков и сниппетов (например, использование тегов [[~id]])
4.Для изображений придётся разрабатывать отдельную систему управления числом просмотров, числом комментариев и прочими realtime-характеристиками. Либо расширять возможности существующей системы (работающей со стандартными ресурсами modx) в направлении использования пользовательских таблиц.

— Склоняюсь к первому варианту. В случае с отдельной таблицей дофига всего писать придётся (и всё написанное придётся постоянно корректировать синхронно с изменениями архитектуры/ядра и логики работы modx).
Ваше видение ситуации? Собственно, интересует не только оптимальный с вашей точки зрения вариант, но и другие ньюансы и потенциальные проблемы (в обоих вариантах), которые я не учёл.
23 комментария
Fi1osof1
Fi1osof 08 августа 2015г в 17:47 #
2.Чуть медленнее будет выполняться фильтрация и сортировка по TV этих изображений. Впрочем это проблема/особенность архитектуры modx (а вернее, т.н. универсальных БД), а никак не проблема выбранного варианта хранения данных изображений
Если речь о десятках и более тысяч документов, то это поможет: habrahabr.ru/post/253737/
n
niibaca-nah 08 августа 2015г в 18:38 #
Здравствуйте, Николай. В тему по Вашей ссылке задам вопрос. Недавно реализовывал то, о чём Вы там писали. Возможности значительно расширяются с подобным подходом. БлагоДарю Вас от всей Души! Однако, не удалось обращаться к своим данным из таблицы site_content, как к стандартным, через плейсхолдеры. К примеру так [[*logo]], пришлось писать сниппет, который восполнил мои нужды (подтягивал данные полей отмеченных в параметре у указанного ресурса). Отсюда вопрос: так и должно быть, или я что-то не так сделал?

P.S.: Немножко дописывал Ваш плагин, который Вы указали на Хабре. Хотел сначало выложить куда-то и скинуть Вам, а потом подумал — зачем Вам нужен мой ГК. :) И раз уж пишу тут, всё-таки предложу. Если интересно — напишите, я выложу куда-нибудь.
Fi1osof1
Fi1osof 08 августа 2015г в 19:20 #
К примеру так [[*logo]], пришлось писать сниппет, который восполнил мои нужды (подтягивал данные полей отмеченных в параметре у указанного ресурса). Отсюда вопрос: так и должно быть, или я что-то не так сделал?
Так вы в смарти-шаблоне попробуйте прописать {$modx->resource->logo}. Так же getdata-процессоры вернут массивы данных ресурсов, содержащих элемент logo. Собственно, мы плейсхолдеры особо не юзаем.
Fi1osof1
Fi1osof 08 августа 2015г в 19:32 #
И раз уж пишу тут, всё-таки предложу. Если интересно — напишите, я выложу куда-нибудь.
Чессказать времени совсем нет что-то смотреть. Сорри.
Pathologic1
Pathologic 08 августа 2015г в 19:03 #
ВАРИАНТ 1. Для каждого графического файла создаётся отдельный ресурс (типа «Документ» или «Статический ресурс») с TV-параметрами

Пожалейте тех, кому потом придется с такой галереей работать.
Pathologic1
Pathologic 08 августа 2015г в 19:27 #
C другой стороны, если «каждый графический файл будет иметь свою собственную страницу на сайте (с описанием, характеристиками, комментариями и пр.)», то разве это галерея? В моем понимании, в галерее создаются изображения, а тут получается, что создаются страницы.
c
cyrax_02 08 августа 2015г в 19:39 #
Пожалейте тех, кому потом придется с такой галереей работать.
Например, Василий, я уверен, выбрал бы именно такой вариант (отдельная таблица).
А что там за проблемы возникнут при работе с такой галереей?
Pathologic1
Pathologic 08 августа 2015г в 20:29 #
Моя реплика относится к «Для каждого графического файла создаётся отдельный ресурс (типа «Документ» или «Статический ресурс») с TV-параметрами» — у Василия я кину на страницу 100 файлов и готово, а тут 100 раз «создать ресурс» — «открыть файл-браузер» — «загрузить картинку» — «выбрать картинку» — «сохранить ресурс».

У Василия вариант 2 получается, потому что ms2Gallery рассчитана на то, чтобы на странице ресурса вывести много картинок. И я бы тоже выбрал вариант 2, но в вашем случае получается, что отдельная страница на картинку, куча характеристик, комментарии — то есть скорость работы с картинками в ms2Gallery нивелируется скоростью заполнения характеристик для каждой картинки. То есть для пользователя будет почти одинаково, что вариант 1, что вариант 2, зато для вас быстрее будет сделать вариант 1.
c
cyrax_02 08 августа 2015г в 21:26 #
В своём проекте я не использую какие-либо сторонние сниппеты и компоненты (кроме компонентов для работы с комментариями), поскольку ни один компонентов не обеспечивает требуемого функционала проекта. Даже элементарно хлебные крошки, пагинация, баннеры, псевдонимы, uri, ajax-подгрузка, редиректы, SEO и многое другое — всё это реализовано собственным кодом с индивидуальной логикой. Соответственно, и сабжевый вопрос подразумевает написание собственного интерфейса для загрузки изображений (но только для загрузки). Именно поэтому, я и не рассматриваю здесь возможность использования сторонних компонентов в качестве критерия выбора. Ну а собственный интерфейс для загрузки изображений будет обеспечивать возможность загрузки и одного изображения, и нескольких одновременно (с указанием характеристик для каждой из них).
c
cyrax_02 08 августа 2015г в 21:37 #
У Василия вариант 2 получается, потому что ms2Gallery рассчитана на то, чтобы на странице ресурса вывести много картинок.
И в вариантах 1 тоже просто вывести много картинок на странице. Только браться они будут не из одной папки на диске (соответствующей одному ресурсу), а из нескольких (зависит от физической организации папок с изображениями) — т.е. делаем выборку требуемых ресурсов-изображений по их TV-характеристикам и получаем url'ы физических файлов.

В случае с ms2Gallery — там ведь нет характеристик у каждого изображения? И связь изображений с ресурсами М:1, а у меня — М: М
c
cyrax_02 08 августа 2015г в 19:39 #
то разве это галерея? В моем понимании, в галерее создаются изображения, а тут получается, что создаются страницы.
Ну так комментарии к изображению, описание изображения, списки ресурсов, с которыми связано изображение и прочая информация, касающаяся конкретного изображения должна же на какой-то странице отображаться. Можно и для такой страницы создать один специальный ресурс+шаблон и выводить там запрошенное изображение со всей информацией. Но в плане SEO эффективнее будет оформить в виде таких страниц сами ресурсы, отвечающие за изображения. Других вариантов нет. Впрочем, это уже не суть важно, как это всё организовать. Кому как нравится. Важно то, как и где организовать хранение данных об изображениях.
Fi1osof1
Fi1osof 08 августа 2015г в 19:31 #
Если вся суть проекта крутится вокруг этой галереи, то такой подход предпочтительней. УРЛы, параметры индексации, ТВ-параметры и все такое.
c
cyrax_02 08 августа 2015г в 19:30 #
Если речь о десятках и более тысяч документов, то это поможет: habrahabr.ru/post/253737/
Вариант хороший. На первый взгляд, даже идеальный:
а) никакие join'ы не требуются
б) каждое поле индивидуально типизировано и проиндексировано — как следствие, сортировка и фильтрация будут выполняться максимально быстро и корректно (для строковых значений сравнение строковое, для числовых — числовое)
в) данные занимают меньше места за счёт индивидуальной типизации (верно, только если оригинальные значения TV-параметров из стандартной таблицы с TV будут удаляться)

Но этот вариант не всегда реализуем. Как, например, в моём случае.
У меня более десяти типов ресурсов, у каждого — по 15-20 TV. Итого — сотни TV. Сортировка и фильтрация выполняется по большинству из них. Да, можно все эти TV (по которым выполняется сортировка и фильтрация) автоматом закинуть в (site_content) и индивидуально типизировать на основе характеристик TV. И сделать всё это программно (имя поля = tv_{id}). В mySQL допускается 4 тысячи полей в таблице. Этого с головой хватит и на текущий, и на будущий функционал. Но проблема в том, что работать с этими полями без индексов не имеет смысла, а максимально допустимое число индексов в таблице mySQL — 64. Вот это ограничение и является определяющим. Даже если для некоторых полей создавать составные индексы, всё равно индексов понадобится более 100. К тому же со временем функционал будет только расширяться, добавляться новые типы ресурсов и новые TV-поля.

Сейчас у меня реализован следующий вариант:
а) все TV-поля дублируются в поле (properties) таблицы ресурсов (в формате json) — это поле используется для выборки TV
б) при фильтрации и сортировках подключаются через JOIN только те TV, которые участвуют в этих фильтрах/сортировках (как правило, их не более 3 за раз, а 3 JOIN'а выполняются вполне себе быстро)
в) в случаях, когда ресурс имеет большое количество TV, а в конечной выборке необходимо получить 2-3 TV-ки, эти TV join'ятся (так быстрее: на json-декодирование большого числа TV нужно время), в остальных случаях для выборки использую поле (properties) с последующим json-декодированием
Fi1osof1
Fi1osof 08 августа 2015г в 19:35 #
в) данные занимают меньше места за счёт индивидуальной типизации (верно, только если оригинальные значения TV-параметров из стандартной таблицы с TV будут удаляться)
Они удаляются.

В целом по проекту: сочувствую…
Pathologic1
Pathologic 08 августа 2015г в 20:32 #
а) все TV-поля дублируются в поле (properties) таблицы ресурсов (в формате json) — это поле используется для выборки TV

Есть еще вариант дублировать их в отдельную таблицу (:
c
cyrax_02 08 августа 2015г в 20:40 #
Есть еще вариант дублировать их в отдельную таблицу (:
Тогда для каждого типа ресурсов придётся свою таблицу создавать с TV (из-за ограничения на число индексов в одной таблице). Ну а коли для каждого типа ресурсов будет своя таблица, то и сами ресурсы логично будет хранить в этих таблицах. А коли ресурсы будут храниться в отдельных таблицах, тогда и modx не нужен.
c
cyrax_02 08 августа 2015г в 19:46 #
В целом по проекту: сочувствую…

В смысле, я что-то не то делаю? Или проект на modx труднореализуем?
Fi1osof1
Fi1osof 08 августа 2015г в 19:56 #
Он просто труднореализуем:) Не важно на чем. Но не безнадежен.
c
cyrax_02 08 августа 2015г в 20:33 #
Чем сложнее проект, тем меньше потенциальных конкурентов
Fi1osof1
Fi1osof 08 августа 2015г в 20:48 #
А еще тем выше риски, издержки и т.п., и соответственно ниже профит и больше срок окупаемости. Тут не все так однозначно.
c
cyrax_02 21 августа 2015г в 22:55 #
> Если речь о десятках и более тысяч документов, то это поможет: habrahabr.ru/post/253737/
> Но этот вариант не всегда реализуем. Как, например, в моём случае.
> В целом по проекту: сочувствую…
Некоторые TV всё-таки пришлось разместить в таблице ресурсов. А именно — числовые поля. И только те числовые, по которым выполняется фильтрация (на больше/меньше) и сортировка. Т.к.:
а) во всех остальных случаях фильтрация и сортировка вполне себе нормально отработает и по строковым TV (с использованием индекса)
б) с числовыми TV-полями при выполнении сортировки и фильтрации (на больше/меньше) пришлось бы выполнять преобразование на лету и как следствие, полный перебор БЕЗ использования индексов
в) в нашем распоряжении имеется всего 44 индекса (64 минус 20 стандартных), соответственно, все TV в таблицу ресурсов не закинешь. Закидываю только необходимый минимум (числовая сортировка/фильтрация)

Но логику, описанную в статье, немного изменил (под свой проект):
1.Числовые TV не перемещаю в таблицу ресурсов, а копирую. Памяти уходит больше, но упрощается логика + повышается безопасность (если что «поломается», всегда можно восстановить значения из стандартных TV)
2.Схему (modx->map) дополняю новыми полями также на лету, но не вручную, а программно — на основе структуры таблицы в БД (использую генератор xPDOGenerator)
3.Описание индексов новых полей в (modx->map) не помещаю, т.к. индексы xpdo нужны только для генерации таблиц в БД (или нужны для чего-то ещё ?)

— Таким образом, получилась гибридная система TV-параметров:
1.Для выборки TV используется поле (properties)
2.Для фильтрации и сортировки по числовым полям используются собственные поля в таблице ресурсов (числовое сравнение)
3.Для фильтрации и сортировки по строковым полям — TV-поля подключаются через join (строковое сравнение)

При такой организации TV:
а) и выборку большого числа TV можно будет сделать довольно быстро (без кучи JOIN'ов)
б) можно быстро (с использованием индекса) выполнять фильтрацию и сортировку как по строковым полям (строковое сравнение), так и по числовым полям (числовое сравнение), исключая преобразование типов на лету
в) можно не заморачиваться тем, что в таблице ресурсов остаётся всего 44 индекса для собственных полей (для числовых полей, по которым выполняется фильтрация/сортировка, их всем хватит)
Fi1osof1
Fi1osof 26 августа 2015г в 13:53 #
3.Описание индексов новых полей в (modx->map) не помещаю, т.к. индексы xpdo нужны только для генерации таблиц в БД (или нужны для чего-то ещё ?)
Нужны только для генерации. Но если вдруг будете потом на основе мапы таблицу создавать, то конечно же они понадобятся.

c
cyrax_02 21 августа 2015г в 22:57 #
И здесь как всегда проблема с индексами возникает. Если, например, в таблице ресурсов мы создаём числовое поле (sCount) и индекс idx_sCount по этому полю, то при выполнении запросов, в которых выполняется фильтрация и по полю published (или deleted), и по числовому полю (sCount) (не важно, в какой последовательности), то MySQL будет использовать индекс published, а не idx_sCount (как этого следовало бы ожидать) — это приведёт к почти полному перебору всех ресурсов (если положить, что почти все ресурсы являются опубликованными). Аналогично и с (deleted).
При этом если в таблице будет индекс по обоим этим полям, то MySQL выберет именно этот индекс (как и должно быть).

Решить проблему можно 3 способами:
1.Для каждого запроса указывать необходимый индекс. Сложности этого способа очевидны:
— сложна реализация (xpdo индексы не поддерживает)
— необходимый индекс придётся указывать для каждого запроса и при изменении имени или структуры индекса придётся все эти запросы пересматривать

2.Для собственных полей указывать составные индексы, начинающиеся со стандартных полей и заканчивающиеся собственными полями (например: idx_published_sCount, idx_classKey_deleted_published_sCount). Но в этом случае часть существующих запросов может начать тормозить, поскольку при наличии 2, 3 и более индексов, начинающихся со стандартных полей, MySQL на некоторых запросах (предположительно, с конструкцией IN + может зависеть и от версии MySql) начинает очень долго выбирать оптимальный индекс: modxclub.ru/topics/vyiborka-iz-%28modtemplatevarresource%29-sushhestvennoe-uskorenie-pri-yavnom-ukazanii-indeksa-1759.html#comment-7177

3.Для собственных полей указывать составные индексы, начинающиеся с собственных полей и заканчивающиеся стандартными (например: idx_sCount_published, idx_sCount_classKey_deleted_published). В этом случае эти индексы MySQL будет рассматривать в качестве возможных только в тех запросах, в которых используются наши собственные поля. И при этом в тех запросах, в которых присутствуют условия и по стандартным полям, и по нашим полям, будет использовать именно эти (наши) составные индексы, а не простые стандартные.
Авторизуйтесь или зарегистрируйтесь (можно через соцсети ), чтобы оставлять комментарии.