2012-05-24 5 views
2

У меня есть три классазапросов и сортировки встроенный документ в Mongoid

class Post 
include Mongoid::Document 
include Mongoid::Timestamps 
belongs_to :user, :inverse_of => nil 
embeds_many :comments, :as => :commentable 
field :content, :type => String 
end 

class Commment 
    include Mongoid::Document 
    include Mongoid::Timestamps 
    belongs_to :user, :inverse_of => nil 
    embedded_in :commentable, :polymoriphic => true 
end 

class User 
    has_many :posts, :dependent => :destroy 
    field :name, :type => String 
end 

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

comments_user=[] 
Post.where("comments.user_id" => user.id). 
    only(:comments). 
    each {|p| comments_user += p.comments.where(:user_id => user.id).to_a} 
latest_comment = comments_user.sort_by{|comment| comment[:updated_at]}.reverse.first 

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

ответ

3

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

Я вижу два варианта здесь:

  • Keep вложение и дублировать данные. То есть, когда пользователь делает комментарий, вставляйте этот комментарий в документ-документ и в пользовательский документ. Конечно, это дублирование данных имеет свои недостатки (что делать, если вам нужно редактировать комментарии?);

  • Остановить внедрение и начать реферирование. Это означает, что комментарий теперь является объектом верхнего уровня. Вы не можете быстро загрузить сообщение с комментариями, потому что нет объединений. Но теперь другие запросы быстрее, и нет дублирования данных.

+0

Ok ... но сейчас я не хочу, чтобы изменить модель только для выполнения этого запроса. Разве нет никакого обходного пути, которое дает мне результат? Хорошо, если результат работает для большинства случаев. :) –

+1

Да, это работает, но это неэффективно. Он выполняет поиск по всем сообщениям, которые пользователь прокомментировал. Решение не является масштабируемым. Если возможно, я хочу что-то эффективное и дает мне ответ в большинстве случаев. –

+0

Невозможно сделать эффективный запрос с помощью вашей текущей схемы. –

5

Это должно принести последнюю Зайти комментарий

Post.where("comments.user_id" => user.id).order_by(:'comments.updated_at'.desc).limit(1).only(:comments).first 
+0

На самом деле, ваш код дает мне последнее сообщение. Мне нужен последний комментарий пользователя. Это дает мне тот же результат, что и ваш: Post.where ("comments.user_id" => user.id) .order_by (: updated_at.desc) .limit (1) .only (: comments) .first –

Смежные вопросы