2012-05-02 87 views
0

我有一个模型与几个嵌入式模型。我需要查询记录以查看它是否存在。问题是,我将不得不包括提及多个嵌入文档我的查询必须包括以下PARAMS:Mongoid复杂查询包含嵌入式文档

{ 
"first_name"=>"Steve", 
"last_name"=>"Grove", 
"email_addresses"=>[ 
    {"type"=>"other", "value"=>"[email protected]", "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缺少这样和联想?

回答

1

有几件事要考虑。

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

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

  3. 否则您在标准声明中写了一个非常尴尬的问题,幸好您可以使用点符号。

喜欢的东西:

UserProfile.where(first_name: "Steve", 
        last_name: "Grove", 
        :email_addresses.matches => {type: "other", 
               value: "[email protected]", 
               primary: "true"}, 
        ..., ...) 
+0

我很想看看js标准会是什么样子的例子。 –

+0

对不起@JasonWaldrip我的mongodb foo不是那么好。 :) – TCopple

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 === "[email protected]"; 
    } 
    return this.first_name === "Steve" && 
     this.last_name === "Grove" && 
     email_match; 
    } 
} 
UserProfile.where(query).first 

这不是很漂亮,但它的工作原理

0

随着Mongoid 3,你可以使用elem_matchhttp://mongoid.org/en/origin/docs/selection.html#symbol

UserProfile.where(:email_addresses.elem_match => {value: '[email protected]', primary: true}) 

这是假设现在

class UserProfile 
    include Mongoid::Document 
    embeds_many :email_addresses 
end 

如果你需要包括这些领域中的每一个,我会建议使用UserProfile.collection.aggregate(query)。在这种情况下,你可以用所有的字段构建一个巨大的散列。

query = { '$match' => { 
    '$or' => [ 
    {:email_addresses.elem_match => {value: '[email protected]', primary: true}} 
    ] 
} } 

它开始有点疯狂,但希望这会让你对你的选择有所了解。另一个例子是https://coderwall.com/p/dtvvha