包含嵌入式文档的Mongoid复杂查询

时间:2012-05-02 15:20:16

标签: ruby ruby-on-rails-3 mongoid

我有一个带有几个嵌入式模型的模型。我需要查询记录以查看它是否存在。问题是我必须包含对多个嵌入式文档的引用,我的查询必须包含以下参数:

{
 "first_name"=>"Steve",
 "last_name"=>"Grove",
 "email_addresses"=>[
     {"type"=>"other", "value"=>"steve@stevegrove.com", "primary"=>"true"}
 ],
 "phone_numbers"=>[
     {"type"=>"work_fax", "value"=>"(720) 555-0631"},
     {"type"=>"home", "value"=>"(303) 555-1978"}
 ],
 "addresses"=>[
     {"type"=>"work", "street_address"=>"6390 N Main Street", "city"=>"Elbert", "state"=>"CO"}
 ],
}

即使缺少某些字段,例如_id和关联,我如何查询所有嵌入式文档?

3 个答案:

答案 0 :(得分:1)

要考虑的一些事情。

  1. 您确定查询HAS包含所有这些参数吗?是否没有此信息的子集唯一标识记录?说(first_namelast_nameemail_addresses.value)。如果你能在较少的工作中完成同样的事情,那么查询所有条件将是愚蠢的。

  2. 在Mongoid中,where条件允许您使用直接javascript,因此如果您知道如何编写javascript标准,则可以将一串javascript传递到其中。

  3. 另外,你还在编写一个非常尴尬的标准声明,谢天谢地,你可以使用点符号。

  4. 类似的东西:

    UserProfile.where(first_name: "Steve", 
                       last_name: "Grove", 
                       :email_addresses.matches => {type: "other", 
                                                    value: "steve@stevegrove.com", 
                                                    primary: "true"}, 
                        ..., ...)
    

答案 1 :(得分:0)

响应嵌入式js的请求:

query = %{
  function () {
    var email_match = false;
    for(var i = 0; i < this.email_addresses.length && !email_match; i++){
      email_match = this.email_addresses[i].value === "steve@stevegrove.com";
    }
    return this.first_name === "Steve" &&
      this.last_name === "Grove" &&
      email_match;
  }
}
UserProfile.where(query).first

它不漂亮,但它有效

答案 2 :(得分:0)

使用Mongoid 3,您可以使用elem_match http://mongoid.org/en/origin/docs/selection.html#symbol

UserProfile.where(:email_addresses.elem_match => {value: 'steve@stevegrove.com', primary: true})

这假定

class UserProfile
  include Mongoid::Document
  embeds_many :email_addresses
end

现在,如果您需要包含这些字段中的每一个,我建议您使用UserProfile.collection.aggregate(query)。在这种情况下,您可以使用所有字段构建一个巨型哈希。

query = { '$match' => {
  '$or' => [
    {:email_addresses.elem_match => {value: 'steve@stevegrove.com', primary: true}}
  ]
} }

它开始变得有点疯狂,但希望这会让你深入了解你的选择可能是什么。 https://coderwall.com/p/dtvvha另一个例子。