2013-12-22 103 views
2

需要一些幫助與基於子文檔屬性的值,但也抑制該子文檔屬性出現在結果的蒙戈查詢。MongoDB的子文檔投影

這裏是我的用戶對象:

{ 
    "username" : "abc", 
    "emails" : [ 
    { 
     "address" : "[email protected]", 
     "default" : true 
    }, 
    { 
     "address" : "[email protected]", 
     "default" : false 
    } 
    ] 
}, 
{ 
    "username" : "xyz", 
    "emails" : [ 
    { 
     "address" : "[email protected]", 
     "default" : false 
    }, 
    { 
     "address" : "[email protected]", 
     "default" : true 
    } 
    ] 
} 

我的目標是讓下面的輸出(用「emails.default」:真實的,但沒有出現在結果中「emails.default」屬性):

{ 
    "username" : "abc", 
    "emails" : [ 
    { 
     "address" : "[email protected]", 
    } 
    ] 
}, 
{ 
    "username" : "xyz", 
    "emails" : [ 
    { 
     "address" : "[email protected]", 
    } 
    ] 
} 

使用$位置操作:

collection.find({"emails.default":true}, {"username":1,"emails.$":1}) 

我得到正確的電子郵件子文檔AP梨,但我仍然得到「emails.default」屬性回:

{ 
    "username" : "abc", 
    "emails" : [ 
    { 
     "address" : "[email protected]", 
     "default" : true 
    } 
    ] 
}, 
{ 
    "username" : "xyz", 
    "emails" : [ 
    { 
     "address" : "[email protected]", 
     "default" : true 
    } 
    ] 
} 

出於某種原因,當我使用這個說法:

collection.find({"emails.default":true}, {"username":1,"emails.address":1}) 

我得到以下結果(好像查詢部分聲明被忽略)

{ 
    "username" : "abc", 
    "emails" : [ 
    { 
     "address" : "[email protected]", 
    }, 
    { 
     "address" : "[email protected]", 
    } 
    ] 
}, 
{ 
    "username" : "xyz", 
    "emails" : [ 
    { 
     "address" : "[email protected]", 
    }, 
    { 
     "address" : "[email protected]", 
    } 
    ] 
} 

幫助非常感謝,在此先感謝。

回答

1

我不認爲這是一個支持的功能。您要求在數組文檔中投影選定的字段。看到這個ticket

但我認爲你的文檔結構會存儲大量冗餘數據。將只有一個默認電子郵件地址。使其成爲父文檔的一部分。更新/預測將會簡單得多。現在您的陣列emails實際上只會存儲電子郵件。

3

隨着操作者的位置(如在MongoDB的2.6),你不能選擇性地排除你上匹配的數組元素的字段。

但是,您可以使用聚合框架MongoDB中2.2+實現你想要的結果:

db.user.aggregate(

    // Match on relevant documents to optimize query 
    { $match: { 
     username: "abc" 
    }}, 

    // Convert the "emails" address into a stream of documents 
    { $unwind: "$emails" }, 

    // Only include the emails with default:true 
    { $match: { 
     "emails.default" : true 
    }}, 

    // Project the desired fields 
    { $project: { 
     _id : 0, 
     username: 1, 
     "emails.address": 1 
    }} 
) 

樣品結果:

{ 
    "username" : "abc", 
    "emails" : { 
     "address" : "[email protected]" 
    } 
}