如何从Mongoid中删除嵌入式文档?

时间:2011-10-03 12:24:57

标签: ruby mongodb mongoid

我在使用Mongoid删除文档时遇到一些问题... 代码实际上删除了库,但我收到一个浏览器错误,如下所示:

  

Mongoid :: Errors :: DocumentNotFound at / admin / galleries / delete / 4e897ce07df6d15a5e000001

可疑代码如下:

def self.removeGalleryFor(user_session_id, gallery_id)
  person = Person.any_in(session_ids: [user_session_id])
  return false if person.count != 1
  return false if person[0].userContent.nil?
  return false if person[0].userContent.galleries.empty?

  gallery = person[0].userContent.galleries.find(gallery_id) #ERROR is on this line
  gallery.delete if !gallery.nil?
end

我的Person类嵌入了一个嵌入许多画廊的userContent。

奇怪的是,我已经有了几个关于这个的测试工作正常......

我真的不确定发生了什么 - 我的画廊似乎很好,甚至从Mongo中删除了。

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

find如果找不到具有给定ID的文档,则会抛出错误。如果不存在,则不要检查给定图库的存在并返回nil,而是在查询时直接询问mongodb以删除任何此类图库。

def self.remove_gallery_for(user_session_id, gallery_id)
  user_session_id = BSON::ObjectId.from_string(user_session_id) if user_session_id.is_a?(String)
  gallery_id = BSON::ObjectId.from_string(gallery_id) if gallery_id.is_a?(String)

  # dropping to mongo collection object wrapped by mongoid, 
  # as I don't know how to do it using mongoid's convenience methods
  last_error = Person.collection.update(
      # only remove gallery for user matching user_session_id
      {"session_ids" => user_session_id}, 
      # remove gallery if there exists any
      {"$pull" => {:userContent.galleries => {:gallery_id => gallery_id}}},
      # [optional] check if successfully removed the gallery
      :safe => true
  )

  return last_error["err"].nil?
end

这样您就不会加载Person,甚至不会将数据从monogdb获取到应用程序服务器。如果它已存在,只需删除它。

但如果您需要触发回调并切换到destroy而非delete

,您应该更喜欢@ fl00r的答案

答案 1 :(得分:0)

def self.removeGalleryFor(user_session_id, gallery_id)
  # person = Person.where(session_ids: user_session_id).first
  person = Person.any_in(session_ids: [user_session_id])
  if person && person.userContent && person.userContent.galleries.any?
    gallery = person.userContent.galleries.where(id: gallery_id).first
    gallery.delete if gallery
  end
end

ps:

在Ruby中,通常使用under_score命名,然后使用CamelCase

答案 2 :(得分:0)

感谢Rubish指出我至少通过我的测试的解决方案 - 由于某种原因fl00r的代码不起作用 - 它看起来应该如此,但不是出于某种原因......

Person.collection.update(
    {"session_ids" => user_session_id},
    {"$pull" => {'userContent.galleries' => {:_id => gallery_id}}},
    :safe => true
)

=>这段代码将通过我的测试,但是一旦它在sinatra中运行它就不起作用......太令人沮丧了!

已经在github上发布了此代码https://github.com/LouisSayers/bugFixes/tree/master/mongoDelete