Моделирование многие-ко-многим: через Mongoid / MongoDB - PullRequest
4 голосов
/ 06 марта 2011

Я относительно новичок в Mongoid / MongoDB, и у меня есть вопрос о том, как смоделировать конкретное отношение многие ко многим.

У меня есть модель User и модель Project.Пользователи могут принадлежать ко многим проектам, и каждое членство в проекте включает одну роль (например, «администратор», «редактор» или «зритель»).Если бы я использовал ActiveRecord, то установил бы связь «многие ко многим» между User и Project, используя has_many :through, а затем поставил бы поле для роли в таблице соединений.

Каков хороший способ моделирования этого сценария в MongoDB и как бы я объявил эту модель с Mongoid?Пример ниже кажется хорошим способом для моделирования этого, но я не знаю, как элегантно объявить реляционную связь между User и встроенным ProjectMembership с Mongoid.

Заранее спасибо!

db.projects.insert(
  { 
    "name" : "Test project",
    "memberships" : [
      {
        "user_id" : ObjectId("4d730fcfcedc351d67000002"),
        "role" : "administrator"
      },
      {
        "role" : "editor",
        "user_id" : ObjectId("4d731fe3cedc351fa7000002")
      }
    ]
  }
)

db.projects.ensureIndex({"memberships.user_id": 1})

1 Ответ

3 голосов
/ 06 марта 2011

Моделирование хорошей схемы Mongodb действительно зависит от того, как вы получаете доступ к своим данным. В описанном вами случае вы проиндексируете свой ключ memberships.user_id, который выглядит нормально. Но ваш размер документа будет расти, так как вы будете добавлять зрителей, редакторов и администраторов. Кроме того, ваша схема будет затруднять создание запросов, таких как:

Запрос проектов, где user_id xxx является редактором:

Опять же, вам, возможно, не нужно запрашивать подобные проекты, поэтому ваша схема выглядит хорошо. Но если вам нужно запросить свои проекты по роли user_id AND, я бы порекомендовал вам создать коллекцию 'project_membership':

db.project_memberships.insert(
  { 
    "project_id" : ObjectId("4d730fcfcedc351d67000032"),
    "editors" : [
      ObjectId("4d730fcfcedc351d67000002"),
      ObjectId("4d730fcfcedc351d67000004")
    ],
    "viewers" : [
      ObjectId("4d730fcfcedc351d67000002"),
      ObjectId("4d730fcfcedc351d67000004"),
      ObjectId("4d730fcfcedc351d67000001"),
      ObjectId("4d730fcfcedc351d67000005")
    ],
    "administrator" : [
      ObjectId("4d730fcfcedc351d67000011"),
      ObjectId("4d730fcfcedc351d67000012")
    ]
  }
)

db.project_memberships.ensureIndex({"editors": 1})
db.project_memberships.ensureIndex({"viewers": 1})
db.project_memberships.ensureIndex({"administrator": 1})

Или еще проще ... добавить индекс в схему проекта:

db.projects.ensureIndex({"memberships.role": 1})
...