mongoid - как сделать запрос по встроенному объекту - PullRequest
0 голосов
/ 19 марта 2012

У меня есть следующая модель:

class User
  include Mongoid::Document
  store_in :users

  field :full_name,   :type => String
end

class Message
  include Mongoid::Document

  embeds_one :sender, :class_name => "User"

  field :text,        :type => String
end

Я хотел бы хранить User и Message в отдельных автономных коллекциях, чтобы их можно было запрашивать напрямую, и я хотел бы иметь одну копиюпользователя для sender в каждой записи сообщения.Правильно ли подходит моя модель для такого рода запросов?

И когда у меня есть экземпляр User user, как я могу запросить сообщения, где sender = user?

Я пытался:Message.where(:sender => user) Message.where('sender.id' => user.id) оба не работают.

только Message.where('sender.full_name' => user.full_name) работал, но я не хочу полагаться на текстовое поле, когда нужно использовать поле id.

Что такоелучший способ сделать это?

Как сохранить сообщение / пользователя:

user = User.new
user.full_name = 'larry'
user.save

m = Message.new(:text => 'a text message')
m.sender = user
m.save

И это приводит к базе данных:

> db.users.find({ 'full_name' : 'larry'})
> db.messages.find({})[0]
{
        "_id" : ObjectId("4f66e5c10364392f7ccd4d74"),
        "text" : "a text message",
        "sender" : {
                "_id" : ObjectId("4f62e0af03642b3fb54f82b0"),
                "full_name" : "larry"
        }
}

Ответы [ 2 ]

1 голос
/ 20 марта 2012

Как объяснить Джордан Дарран (ведущий разработчик Mongoid) в группе Google Mongoid: http://groups.google.com/group/mongoid/browse_thread/thread/04e06a8582dbeced#

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

class Sender 
  include Mongoid::Document 
  include UserProperties 

  class << self 
    def from_user(user) 
      Sender.new(user.attributes) 
    end 
  end 
end 

class User 
  include Mongoid::Document 
  include UserProperties 
end 

module UserProperties 
  extend ActiveSupport::Concern 
  included do 
    field :full_name, type: String 
  end 
end 

class Message 
  include Mongoid::Document 
  embeds_one :sender 
end 

Вам также не нужен макрос: store_in для пользователя - по умолчанию это имя будет "пользователи".

1 голос
/ 19 марта 2012

Вы не можете делать то, что делаете.

Ваш пользовательский документ сохранен в его одной коллекции, потому что вы используете метод store_in.И вы попытаетесь сохранить его в другом документе (Message)

Если вы действительно хотите 2 коллекции, вам нужно использовать has_one :user в вашем классе Message.

class Message

  has_one :sender, :class_name => 'User', :foreign_key => 'sender_id'

end

Послевы можете получить ваше сообщение как:

Message.senders, чтобы иметь всех ваших отправителей.

...