2013-10-07 48 views
3

我已存儲在MongoDB中的一個文件:如何找到在貓鼬ID子文檔,並排除某些領域

shop: { 
    _id: '...' 
    title: 'my shop' 
    users: [ 
    { 
     _id: '...', 
     name: 'user1', 
     username: '...' 
    }, 
    { 
     _id: '...', 
     name: 'user2', 
     username: '...' 
    } 
    ] 
} 

我用這個查詢他的ID來獲得子文檔用戶:

Shop.findOne({'users._id': userId}, {'users.$': 1}, function (err, user) { 
    console.log(user); 
}); 

輸出:

{ _id: ..., 
    users: 
    [{ 
    name: 'user1', 
    username: '...', 
    _id: ... 
    }] 
} 

我怎樣才能篩選結果只返回用戶名。 我現在就這樣做的方式:

Shop.findOne({'users._id': userId}, {'users.$': 1}, function (err, shop) { 
    shop = shop.toObject() 
    user = shop.users[0] 
    filtered = { 
    name: user.name 
    } 
    callback(filtered); 
}); 

但有一個更好的方式來做到這一切在查詢?

回答

2

這個問題差不多兩歲了,但我注意到人們仍然在尋找解決這個問題的辦法。 fernandopasik的回答非常幫助我,但是缺少關於如何使用建議的聚合操作的代碼示例。這就是爲什麼我發佈更詳細的答案。 我所使用的文件是:

{ 
    _id: '...' 
    title: 'my shop' 
    users: [ 
    { 
     _id: 'user1Id', 
     name: 'user1', 
     username: '...' 
    }, 
    { 
     _id: 'user2Id', 
     name: 'user2', 
     username: '...' 
    } 
    ] 
} 

我想出了一個解決方案(閱讀聚合MongoDB的文檔後)爲:

Shop.aggregate([ 
    {$unwind: '$users'}, 
    {$match: {'users._id': 2}}, 
    {$project: {_id: 0, 'name': '$users.name'}} 
]); 

要了解聚合是如何工作的,這是最好的嘗試一次執行一個操作並讀取此操作的mongodb文檔。

  1. Shop.aggregate([{$unwind: '$users'}])

$放鬆解構用戶陣列(不要忘了包括$陣列名稱),所以你最終:

{ 
    _id: '...', 
    title: 'my shop', 
    users: { 
    _id: 'user1Id', 
    name: 'user1', 
    username: '...' 
    } 
} 
{ 
    _id: '...', 
    title: 'my shop', 
    users: { 
    _id: 'user2Id', 
    name: 'user2', 
    username: '...' 
    } 
} 

2。在彙總管道上使用{$match: {'users._id': 'user2Id'}}(本例中的兩個文檔)將返回users._id爲'user2Id'的整個文檔:

{ 
    _id: '...', 
    title: 'my shop', 
    users: { 
    _id: 'user2Id', 
    name: 'user2', 
    username: '...' 
    } 
} 

3只返回名稱:「用戶2」,你可以使用{$project: {_id: 0, 'name': '$users.name'}}

{name: 'user2'} 

聚集管道是不容易在第一把握。我建議通讀mongodb聚合文檔並嘗試一次聚合操作。有時很難發現整個聚合管道中的錯誤。大多數情況下,當流水線中存在錯誤時,您只需從管道中獲取任何結果文檔。