2012-05-02 86 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