Anonymous
Anonymous
yopp
Anonymous
в разрезе каждого пользователя, то есть я ожидаю
что юзер 1 из страны А прошел 1 км за 10 дней
Anonymous
и тд
Anonymous
снова не до конца объяснил)
yopp
не очень понимаю
Anonymous
не очень понимаю
ну смотри
я хочу получить стату по пользователям из страны А
их например всего 10к
я хочу узнать, сколько пробежал каждый из них с даты А по дату Б
{ id: 1, metrika1: 10000, id: 2, metrika1: 0 } etc
yopp
ага, ну тоесть есть три измерения, которые позволяют уменьшить размер выборки
yopp
разницы в объёме информации необходимой для расчёта «пробежали все» и «пробежал каждый» нет :)
yopp
смысл оптимизации всегда сводиться к уменьшению размера выборки необходимой для анализа
yopp
а сколько измерений у каждого пользователя?
yopp
страна, город?
yopp
дата активности не уменьшает выборку
yopp
так как у вас активность это часть документа
yopp
но вам всё ещё надо прочитать историю по max(500к*1000*10) метрикам :)
Anonymous
да, это проблема ) собсна возвращаясь к первому самому сообщению про гуд практис)
yopp
нет серебрянной пули
yopp
Anonymous
я понимаю, наверняка уже кто-то сталкивался с такой проблемой, не я первый)
yopp
и тут важный вопрос сколько «корневых» измерений у пользователя
yopp
yopp
у вас многомерные данные, вы хотите по ним строить аналитику
yopp
это частный случай OLAP
yopp
генерализированный OLAP в монге это адски дорого
yopp
а вот domain specific не очень
Anonymous
не так прочитал
yopp
похоже так :)
Anonymous
что значит коернвые измерения?)
yopp
у вас есть страна, а что ещё? какие ещё свойства по которым вы хотите выбирать пользователей?
yopp
возраст? пол?
Anonymous
возраст? пол?
это все high-level поля, там супер небольшие сеты из 2-3 элементов
самый основной - дата и тип, по сути все)
yopp
если их 2-3, тогда более-менее понятно
yopp
я бы разбил на бакеты по месяцу, на каждого пользователя по каждой метрике
yopp
{
user_id: ObjectId(),
user_country: ...,
user_age: ...,
metric_id: ObjectId,
start_date: ISODate("2020-01-01"),
end_date: ISODate("2020-01-31"),
values: [
{
date: ISODate("2020-01-01"),
value: 500
}
...
]
}
Anonymous
yopp
да, есть
yopp
index based
yopp
но с вашей схемой, это вам почти не поможет
Anonymous
yopp
не только по месяцам
yopp
а по 3 измерениям
yopp
пользователь, дата, метрика
yopp
+ метаданные
yopp
можно кстати с метаданными тоже красиво поступить
yopp
{
user_id: ObjectId(),
user_meta: [
{
meta_id: ObjectId(),
meta_value: ...
}
]
metric_id: ObjectId,
start_date: ISODate("2020-01-01"),
end_date: ISODate("2020-01-31"),
values: [
{
date: ISODate("2020-01-01"),
value: 500
}
...
]
}
yopp
и можно сделать два индекса
yopp
start_date, user_id, values.value
и meta.meta_id, meta.meta_value, start_date, user_id, values.value
yopp
первый позволит эффективно выбирать данные без фильтра по мета-данным пользователей
yopp
например сколько пользователь X пробежал за Y дней
Anonymous
так я с таким успехом мог пг заюзать с реляциями)
yopp
а второй с учётом мета-данных
сколько пользователи из страны Z прошли за Y дней
yopp
нет, с таким успехом бы не смогли
yopp
немного с другим
yopp
но мне кажется вы ошибочно считаете что документ можно читать частично
Anonymous
с таким же подходом)
Anonymous
yopp
нет, документ можно прочитать только целиком
yopp
с точки зрения хранилища документ это просто bson blob
Anonymous
ага
Anonymous
я понял
Anonymous
тогда все так себе
yopp
монгу проще всего представить как key/value хранилище с нативной поддержкой bson в значениях
yopp
Anonymous
для моего кейса, тк с течением времени дкоументы будут только деградировать
yopp
я вам предложил очень простую схему, которая позволит вам эффективно выбирать и партицировать документы
yopp
у этой схемы есть немного минусов, в перую очередь это update cost в случае изменения у пользователя мета-данных
yopp
но это объективно очень редкая операция
yopp
а за счёт высокой локализации и достаточно небольшого количества документов принадлежащих каждому пользователю, это будет _очень_ быстро
yopp
т.е. за 20 лет, при 10 метриках у пользователя будет всего 2 400 документа
yopp
второй плюс: эта схема позволяет делать преагрегаты
Anonymous
я немного не понял идею с метой
с айдишкой ок, а что какое значение имеет meta_value ?
yopp
и при патицировании вы сможете поделить данные на «горячие» и «холодные»
yopp
yopp
а meta_value это значение для этого класса
yopp
непосредственно страна или возраст
yopp
есть второй подход сделать meta_value_id и сложить в массив
yopp
если нет метаданных с большим количеством возможных значений, то тоже сработает