2016-04-14 127 views
0

我想在子文檔中搜索。這是我的我的文檔的結構:MongoDB - 搜索子文檔

{ 
    _id: <ObjectID>, 
    email: ‘[email protected]’, 
    password: ‘12345’, 
    images: [ 
     { 
      title: ‘Broken Hand’, 
      description: ‘Here is a full description’, 
      comments: [ 
       { 
        comment: ‘Looks painful’, 
       } 
      ], 
      tags: [‘hand’, ‘broken’] 
     } 
    ] 
} 

,我希望能夠找到具有特定標籤的所有用戶的所有圖像,但我使用的查詢只返回將其與找到的第一個圖像標籤:

db.site_users.find({'images.tags': "broken"}, {images: 1, images: {$elemMatch: { 'tags': 'broken'}}}).pretty() 

有人可以請指出我在正確的方向如何我可以得到所有的圖像?

+0

你的元素匹配似乎是在項目部分,而不是過濾器部分(但我可能會誤解)。嘗試:'db.site_users.find({'images.tags':「broken」,{images:{$ elemMatch:{'tags':'broken'}}},{images:1})。pretty()' ? –

回答

0

您可以使用該aggregation framework

db.site_users.aggregate([ 
    {$unwind: "$images"}, 
    {$match:{ 
     "images.tags": "broken" 
    }} 
]) 
0

查詢是很好的,因爲它的文件相匹配,但「投影」是的,你可以用.find()做什麼範圍之內,你需要.aggregate(),並注意不要從陣列中刪除「圖像」項目,只有不匹配的「標籤」。

理想情況下,你做這個有MongoDB的3.2使用​​內$project

db.site_users.aggregate([ 
    { "$match": { "images.tags": "broken" }}, 
    { "$project": { 
     "email": 1, 
     "password": 1, 
     "images": { 
      "$filter": { 
       "input": "$images", 
       "as": "image", 
       "cond": { 
        "$setIsSubSet": [["broken"], "$$image.tags"] 
       } 
      } 
     } 
    }} 
]) 

或者可能使用$map$setDifference這也與MongoDB的2.6兼容,只要在「圖像」的內容是「獨一無二」的每個條目。這是由於「設置」操作,其中「套」是「獨一無二」:

db.site_users.aggregate([ 
    { "$match": { "images.tags": "broken" }}, 
    { "$project": { 
     "email": 1, 
     "password": 1, 
     "images": { 
      "$setDifference": [ 
       { "$map": { 
        "input": "$images", 
        "as": "image", 
        "in": { 
         "$cond": { 
          "if": { "$setIsSubSet": [["broken"], "$$image.tags" ] }, 
          "then": "$$image", 
          "else": false 
         } 
        } 
       }}, 
       [false] 
      ] 
     } 
    }} 
]) 

它可以在早期版本的MongoDB做,但可能是最好的避免因處理$unwind對成本數組:

db.site_users.aggregate([ 
    { "$match": { "images.tags": "broken" }}, 
    { "$unwind": "$images" }, 
    { "$match": { "images.tags": "broken" }}, 
    { "$group": { 
     "_id": "$_id", 
     "email": { "$first": "$email" }, 
     "password": { "$first": "$password" }, 
     "images": { "$push": "$images" } 
    }}  
]) 

由於通常使用$unwind爲了這個目的,你是不是「聚集」任何事情,那麼,如果你沒有一個現代版本在其他實際可用的方法相當大的代價,這是通常最好接受在客戶端代碼中而不是在服務器上「過濾」數組內容本身。

因此,對於這種情況,您應該只使用$unwind,其中數組條目將通過刪除不匹配項目的順序「顯着」減少。否則,處理成本可能高於傳輸數據的網絡成本,並且任何好處都將被否定。

如果你沒有現代版本,那麼得到一個。這些功能與實用和性能完全不同。