eshcherbin / save-the-moment

SPbAU educational Android project
0 stars 0 forks source link

Придумать устройство БД для хранения моментов #5

Closed eshcherbin closed 7 years ago

eshcherbin commented 7 years ago

@krinkinmu, можете помочь с разработкой архитектуры базы данных моментов? Просто нужно сделать это быстро, а курса БД у нас ещё не было, поэтому я столкнулся с трудностями при хранении тегов и не знаю, как их решить.

У меня пока что есть два варианта:

  1. Есть одна таблица, в которой хранятся все моменты, при этом каждому столбцу соответствует поле в классе Moment, а теги хранятся в виде одной строки через запятую. Есть существенная проблема: фильтрацию по тегам сделать средствами БД, как я понимаю, невозможно.
  2. Есть таблица моментов, в которой хранится всё, кроме тегов, и таблица тегов в формате (tag_id, moment_id, name). Такой вариант кажется мне получше, но я не до конца понимаю, удобен ли он будет для наших целей. Например, когда я захочу получить все моменты и отобразить каждый вместе со всеми его тегами, у меня наверняка не получится сделать это с помощью стандартного адаптера (в лучшем случае, я сделаю join на moments.id = tags.moment_id и получу на каждый момент столько строчек, сколько тегов для него есть, что не слишком хорошо).

В общем, есть ли какие-то предложения или подсказки, в каком направлении думать?

eshcherbin commented 7 years ago

В принципе, для второго варианта у меня есть такая схема:

  1. В AsyncTask, который будет подгружать моменты из БД, получить Cursor моментов без тегов
  2. Пройтись по нему и для каждого момента получить Cursor тегов.
  3. Построить по данной информации List и возращать уже его.

Кажется, что не так уж и плохо.

krinkinmu commented 7 years ago

2016-11-20 16:28 GMT+03:00 Egor Shcherbin notifications@github.com:

@krinkinmu https://github.com/krinkinmu, можете помочь с разработкой архитектуры базы данных моментов? Просто нужно сделать это быстро, а курса БД у нас ещё не было, поэтому я столкнулся с трудностями при хранении тегов и не знаю, как их решить.

У меня пока что есть два варианта:

  1. Есть одна таблица, в которой хранятся все моменты, при этом каждому столбцу соответствует поле в классе Moment, а теги хранятся в виде одной строки через запятую. Есть существенная проблема: фильтрацию по тегам сделать средствами БД, как я понимаю, невозможно.

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

  1. Есть таблица моментов, в которой хранится всё, кроме тегов, и таблица тегов в формате (tag_id, moment_id, name). Такой вариант кажется мне получше, но я не до конца понимаю, удобен ли он будет для наших целей. Например, когда я захочу получить все моменты и отобразить каждый вместе со всеми его тегами, у меня наверняка не получится сделать это с помощью стандартного адаптера (в лучшем случае, я сделаю join на moments.id = tags.moment_id и получу на каждый момент столько строчек, сколько тегов для него есть, что не слишком хорошо).

В общем, есть ли какие-то предложения или подсказки, в каком направлении думать?

Моя идея такая:

  1. Таблица с моментами:
    • в этой таблице каждый момент должен иметь уникальный идентификатор (для таких идентификаторов можно использовать автоинкрементирующееся целое число)
    • в этой же таблице хранится обзщие аттрибуты момента, т. е. такие которые есть у каждого момента не более чем в одном экземпляре (например, координаты, дата и время, какое-то имя, если оно есть и тд и тп)
  2. Таблица связывающая идентификаторы моментов с тегами:
    • таблица хранит пары идентификатор момента + строка с именем тега
  3. Медиа файлы и т. д. и т. п.
    • таблица хранит пары идентификатор момента + имя файла и возможно какие-то аттрибуты (вроде типа файла)
    • если один файл может быть сразу в нескольких моментах, то для файлов можно завести отдельную таблицу, так же как и для таблицы с моментами хранить там идентификатор, и использовать этот идентификатор для связи медиа файла с моментами.

Теперь, как искать моменты по тегам. Пусть у вас есть список тегов, где каждый тег уникален, делаем Select из Inner Join таблиц 1 и 2 по идентификатору момента, в Where делаем сравнение с тегами из списка через Or, добавляем GroupBy по идентификатору момента, и делаем Count по количеству различных тегов. Итого на выходе этого запроса вы получите записи состоящие из: идентификатора момента, количества различных тегов из списка, которые связаны с моментом. Соответсвенно, если количество тегов совпадает с размером списка - у вас точное совпадение, чем ближе к этом числу тем больше тегов совпало (т. е. можно делать простое неточное совпадение).

Соответственно, при создании момента, нужно в таблицу с парами (идентификаор момента, тег) добавить все теги связанные с моментом.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/eshcherbin/save-the-moment/issues/5, or mute the thread https://github.com/notifications/unsubscribe-auth/ABH4cxmqSfc7sSlMynWV0b0xIXI-_sjKks5rAEsZgaJpZM4K3iYB .

eshcherbin commented 7 years ago

А насколько важно иметь автоинкрементирующееся целое число в качестве id? Нами в коде будет использовать идентификатор в каком-то виде (например, чтобы определять имя папки в Google Drive), но дело в том, что табличный id будет появляться только при вставке в таблицу, а хотелось бы иметь его сразу при создании момента. Нормальным ли будет подход, при котором хранящийся id -- какая-то строка, сгенерированная при создании, например, текущее время или что-то около того?

krinkinmu commented 7 years ago

2016-11-21 17:02 GMT+03:00 Egor Shcherbin notifications@github.com:

А насколько важно иметь автоинкрементирующееся целое число в качестве id? Нами в коде будет использовать идентификатор в каком-то виде (например, чтобы определять имя папки в Google Drive), но дело в том, что табличный id будет появляться только при вставке в таблицу, а хотелось бы иметь его сразу при создании момента. Нормальным ли будет подход, при котором хранящийся id -- какая-то строка, сгенерированная при создании, например, текущее время или что-то около того?

не принципиально важно, главное, чтобы он был уникальным, но использовать текущее время не самая лучшая идея - предствьте, что одним drive-ом пользуются с двух устройств и случится коллизия имен, лучше использовать java.util.UUID.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/eshcherbin/save-the-moment/issues/5#issuecomment-261945943, or mute the thread https://github.com/notifications/unsubscribe-auth/ABH4c8a6RLwU4RbDXyoE8wJ5RvHEXJ7eks5rAaRfgaJpZM4K3iYB .