Rails Mongoid : 查询嵌入文档并访问 Mongoid 条件

Rails Mongoid : Query embedded document and access to Mongoid criteria

我有一个应用程序,用户可以创建很多旅行,他们可以邀请他们的 facebook 好友。在旅行证件中,有一个字段"participants"是一个嵌入文档,Participant模型嵌入在Travel模型中。

这是我的模型:

class Travel
  include Mongoid::Document
  include Mongoid::Timestamps

  # relations
  belongs_to :user

  # fields
  field :title, type: String
  field :description, type: String
  field :begin_date, type: Date
  field :end_date, type: Date
  field :budget, type: Integer
  field :go_back, type: Boolean
  field :title_namespace, type: String

  # friends
  embeds_many :participants
  accepts_nested_attributes_for :participants

end

class Participant
  include Mongoid::Document
  include Mongoid::Timestamps

  field :name, type: String
  field :user_id, type: String

  # relations
  embedded_in :travel, :inverse_of => :participants

end

当我尝试显示已邀请用户的旅行时,请求如下:

@travel_participations = Travel.where('participants.user_id' => @user.id)

我没有任何结果,即使我在 byebug 中有这一行 :

#<Mongoid::Criteria
  selector: {"participants.user_id"=>BSON::ObjectId('592c8da58511989ec850921e')}
  options:  {}
  class:    Travel
  embedded: false>

所以当我把它放在我的视图中时:

<% unless @participations.nil? %>
  <% @travel_participations.each do |travel_participation| %>
    <p> <%= travel_participation.title %> </p>
  <% end %>
<% end %>

我试过 .all.first.to_a.as_json,没有结果……有人知道问题出在哪里吗?

你的嵌入式模型中有这个:

field :user_id, type: String

但您的查询使用的是 BSON::ObjectId:

Travel.where('participants.user_id' => @user.id)

如原始查询所示:

selector: {"participants.user_id"=>BSON::ObjectId('592c8da58511989ec850921e')}

您的嵌入式文档可能有一个 string 字段,例如:

"user_id": "592c8da58511989ec850921e"

而不是您要查找的ObjectId

"user_id": ObjectId("592c8da58511989ec850921e")

因此,由于类型不匹配,您将找不到您要查找的内容。

要么修复嵌入字段的类型:

field :user_id, type: BSON::ObjectId

或按字符串查询:

Travel.where('participants.user_id' => @user.id.to_s)

更改类型将涉及修复您已有的任何数据,以不同的方式更改查询是丑陋的。

有时 Mongoid 会为您在字符串和 ObjectId 之间进行转换,有时不会。当我使用 Mongoid 时,我将 to_bson_id 方法修补到 BSON::ObjectIdStringMongoid::Document、...这样我就可以说:

Model.where(:some_id => some_id.to_bson_id)

而且不必经常担心 some_id 是什么类型。我还确保所有 ID 字段始终指定为 BSON::ObjectId.