денормализация с монгоидом - PullRequest
1 голос
/ 20 апреля 2011

Каков наилучший способ отмены нормализации с помощью mongoid и Rails?

Использование «встроенных» отношений, похоже, не работает (или не предназначено для чего-либо, кроме встраивания целых, оригинальных документов).

Мое настоящее решение хранит и извлекает ненормализованные атрибуты в виде OrderedHash:

collection.update({_id: id, ...}, {..., denormalized: {_id: other.id, _type: other._type, a: other.a, b: other.b}}

def denormalized
  Mongoid::Factory.build(attributes[:denormalized]["_type"], attributes[:denormalized])
end

edit: я должен упомянуть, что я действительно пытался https://github.com/logandk/mongoid_denormalize

Это выравниваетденормализованные атрибуты (в приведенном ниже примере он будет хранить имя_пользователя вместо автора: {имя: "значение"} и не поддерживает множественные денормализованные отношения (например, авторы: [{имя: "Первый соавтор",_id: 1}, {name: «Второй соавтор», _id: 2}])

edit: был запрошен пример.

class User # this class uses STI so _type field is important
  include Mongoid::Document

  field :name # this is the field I want to de-normalize to where Users are referenced

   def write_book
     Book.create!({title: "Some Text", author: {_id: self.id, _type: self._type, name: self.name})
   end
end

class Book
  include Mongoid::Document

  field :title

  # embeds_one :author, polymorphic: true
  # tried this but it doesn't seem to be correct usage... it sort of works but
  # I run into problems with cycles and infinite loops when used extensively
  # because (I think) of how mongoid works internally, expecting embeds_one
  # to mean something different

  def author
    Mongoid::Factory.build(attributes[:author]["_type"], attributes[:author])
  end
end

Правильное решение будет иметь методы ActiveModelнапример new_record? работает, а также помощники по маршрутизации * _path и * _url.

1 Ответ

0 голосов
/ 21 апреля 2011

Это сохранит пользователя как вложенный авторский документ внутри книги.

class User
  include Mongoid::Document
end

#instead of the write book method, you could just do this:
book = Book.create(title: "Old Man And The Sea", users: [user])

class Book
  include Mongoid::Document

  embeds_many :authors

  field :title

  def users=(users)
    users.each do |user|
      authors.build(user: user, name: user.name)
    end
  end
end

class Author
  include Mongoid::Document

  embedded_in :book
  referenced_in :user

  field :name
end
...