Как реализовать эту схему в MongoDB?

Я пытаюсь написать отслеживание script, и у меня возникают проблемы с выяснением того, как должна работать база данных.

В MySQL я бы создал таблицу, которая похожа на

User:
   username_name: string

Campaign:
   title: string
   description: string
   link: string

UserCampaign:
   user_id: integer
   camp_id: integer

Click:
   os: text
   referer: text
   camp_id: integer
   user_id: integer

Мне нужно уметь:

  • См. информацию от каждого клика, такого как IP, Referer, OS и т.д.
  • Посмотрите, сколько часто кликов происходит от X IP, X Referer, X OS
  • Свяжите каждый клик с пользователем и кампанией

Если я что-то делаю в строках

User {
     Campaigns: [
         {
           Clicks: []
         }
     ]
}

У меня возникают две проблемы:

  • Он создает новый объект кампании для каждого пользователя, что является проблемой, потому что, если мне нужно обновить мою кампанию, мне нужно будет обновить объект для каждого пользователя.
  • Я ожидаю, что массив Clicks будет содержать БОЛЬШОЕ количество данных, я чувствую, что его часть объекта User будет очень медленной для запроса.

Ответ 1

Хорошо, я думаю, вам нужно разбить это на основные "разновидности".

У вас есть два объекта "entity":

  • User
  • Campaign

У вас есть один объект "mapping":

  • UserCampaign

У вас есть один "транзакционный" -стильный объект:

  • Click

Шаг 1: объект

Начнем с простых: User и Campaign. Это действительно два отдельных объекта, ни один из них не зависит от другого для его существования. Там также нет скрытой иерархии между двумя: пользователи не принадлежат к Кампаниям, и Кампании не принадлежат Пользователям.

Когда у вас есть два объекта верхнего уровня, подобные этому, они обычно зарабатывают свою собственную коллекцию. Поэтому вам понадобится коллекция Users и коллекция Camapaigns.

Шаг 2: отображение

UserCampaign в настоящее время используется для отображения N-to-M. Теперь, в общем, когда у вас есть сопоставление N-to-1, вы можете поместить N внутри 1. Однако при сопоставлении N-to-M вам обычно нужно "выбрать сторону".

В теории вы можете сделать одно из следующих действий:

  • Поместите список Campaign ID внутри каждого User
  • Поместите список Users ID внутри каждого Campaign

Лично я бы сделал # 1. Вероятно, у вас больше пользователей, чем в кампаниях, и вы, вероятно, захотите разместить массив там, где он будет короче.

Шаг 3: транзакционный

Клики - это совсем другой зверь. В объектных терминах вы можете подумать о следующем: Clicks "принадлежит" a User, Clicks "относятся к" a Campaign. Таким образом, теоретически, вы можете просто хранить клики, являются частью любого из этих объектов. Легко думать, что клики принадлежат пользователям или кампаниям.

Но если вы действительно копаете глубже, вышеупомянутое упрощение действительно ошибочно. В вашей системе Clicks действительно являются центральным объектом. Фактически, вы даже можете сказать, что пользователи и кампании действительно просто "связаны с" щелчком.

Взгляните на вопросы/запросы, которые вы задаете. Все эти вопросы фактически сосредоточены вокруг кликов. Пользователи и кампании не являются центральным объектом в ваших данных, клики.

Кроме того, клики будут самыми обильными данными в вашей системе. У вас будет больше кликов, чем что-либо еще.

Это самая большая заминка при разработке схемы для таких данных. Иногда вам нужно отталкивать "родительские" объекты, когда они не самые важные. Представьте себе создание простой системы электронной коммерции. Ясно, что orders будет "принадлежать" Users, но orders является таким центральным для системы, что он станет объектом верхнего уровня.

Обернуть его

Вероятно, вам понадобятся три коллекции:

  • Пользователь → имеет список campaign._id
  • кампании
  • Клики → содержит user._id, campaign._id

Это должно удовлетворять всем вашим запросам:

См. информацию от каждого клика, такого как IP, Referer, OS и т.д.

db.clicks.find()

Посмотрите, сколько часто кликов происходит от X IP, X Referer, X OS

db.clicks.group() или запустите Map-Reduce.

Свяжите каждый клик с пользователем и кампанией

db.clicks.find({user_id : blah}) Можно также нажать идентификаторы кликов для пользователей и кампаний (если это имеет смысл).

Обратите внимание, что если у вас много и много кликов, вам действительно придется анализировать запросы, которые вы запускаете больше всего. Вы не можете индексировать в каждом поле, так что вы часто захотите запустить Map-Reduces для "свертывания" данных для этих запросов.

Ответ 2

Основная проблема, которую я вижу здесь, заключается в том, что вы пытаетесь применить концепции реляционной базы данных к базе данных, ориентированной на документ. Основное различие между ними состоит в том, что вы не беспокоитесь о схеме или структуре в базе данных NOSQL, а о сборке и документах.

Очень важно/необходимо понимать, что нет понятий объединения во многих реализациях NOSQL, как в SQL. Это означает, что если вы распространяете свои данные по коллекциям, тогда вы будете много работать, чтобы приклеить их позже. Кроме того, нет никакой другой выгоды, распространяя ваши данные в коллекциях, как при нормализации SQL db. Вам нужно подумать, какие данные являются частью вашего документа и к какой коллекции он относится и не беспокоится о реализации под NOSQL db. Поэтому для вашей проблемы ответ может быть... и будет поддерживать все, что вы просили...

db.trackclicks == > коллекция
trackclick = {         ОС: XP,         Пользователь: John Doe,         Кампания: {title: test, desc: test, link: url},         Referrer: google.com         }

Ответ 3

  • Это не проблема для mongodb для обновления большого количества документов, если что-то в какой-то компании было изменено.

  • Вложенная коллекция или вообще не зависит от того, сколько данных в коллекции. В вашем случае, если вы знаете, что коллекция "Клики" будет содержать "БОЛЬШОЕ количество данных", вам нужно создать отдельную коллекцию. Потому что для "кликов" вам понадобятся пейджинг, фильтрация и т.д., А пользователь будет "легкой" коллекцией.

Поэтому я предлагаю следующее:

User {
     Campaigns: []
}

Clicks {
 user_id,
 camp_id
}