2013-05-12 2 views
1

Я получил коллекцию блог, где посты встраиваются в:

db.blogs.insert({ 
    name: 'Smashing Magazine', 
    url: 'http://www.smashingmagazine.com/', 
    posts: [{ 
     date: new Date('2013-05-10'), 
     title: 'How To Avoid Duplicate Downloads In Responsive Images', 
     url: 'http://mobile.smashingmagazine.com/2013/05/10/how-to-avoid-duplicate-downloads-in-responsive-images/', 
     tags: ['Responsive Design', 'Techniques']}] 
}); 

Я хотел бы выполнить запрос, который возвращает все сообщения с дополнительным логическим полем, которое представляет, если определенный тег существует или нет для каждого сообщения. Это то, что я пробовал и не смог:

db.blogs.aggregate(
    {$unwind: "$posts"}, 
    {$project: { 
     name: 1, 
     date: "$posts.date", 
     title: "$posts.title", 
     // isResponsiveDesign should be true or false based on if the post is tagged as "Responsive Design" or not 
     isResponsiveDesign: {$and: [{"$posts.tags": 'Responsive Design'}]} 
    }} 
); 

Каков правильный способ написания этого запроса?

ответ

1

Единственный способ, которым я мог понять это как совокупность, оказался довольно длинным. Моделирование запроса в качестве операции уменьшения карты может быть проще и проще. В любом случае, здесь мы идем:

db.blogs.aggregate([ 
    {$unwind: '$posts'}, 

    // Grab the only fields we'll need 
    {$project: { 
    name: 1, 
    posts: 1 
    }}, 

    // Generate a document for each tag within each post 
    {$unwind: '$posts.tags'}, 

    // Add an attribute to post tags which are equivalent to our search 
    // term 
    {$project: { 
    name: 1, 
    posts: 1, 
    isResponsiveDesign: { 
     $cond: [{$eq: ['$posts.tags', 'Responsive Design']}, 1, 0] 
    } 
    }}, 

    // Recombine so that we have one document per post. Use '$max' to 
    // simulate a boolean OR between two documents' binary 
    // 'isResponsiveDesign' fields 
    {$group: { 
    _id: '$_id', 
    posts: {$push: '$posts'}, 
    isResponsiveDesign: {$max: '$isResponsiveDesign'} 
    }} 
]); 

Это результат агрегации, используя предоставленные вами данные примера. Я добавил тупую копию документа, который вы дали с тегом «Отзывчивый дизайн», который был удален, чтобы проверить.

{ 
    "result" : [ 
     { 
      "_id" : ObjectId("51901e3a8fa65c820b9aae85"), 
      "posts" : [ 
       { 
        "date" : ISODate("2013-05-10T00:00:00Z"), 
        "title" : "How To Avoid Duplicate Downloads In Responsive Images", 
        "url" : "http://mobile.smashingmagazine.com/2013/05/10/how-to-avoid-duplicate-downloads-in-responsive-images/", 
        "tags" : null 
       }, 
       { 
        "date" : ISODate("2013-05-10T00:00:00Z"), 
        "title" : "How To Avoid Duplicate Downloads In Responsive Images", 
        "url" : "http://mobile.smashingmagazine.com/2013/05/10/how-to-avoid-duplicate-downloads-in-responsive-images/", 
        "tags" : "Techniques" 
       } 
      ], 
      "isResponsiveDesign" : 0 
     }, 
     { 
      "_id" : ObjectId("5190190f6ab03ad381d1cb0f"), 
      "posts" : [ 
       { 
        "date" : ISODate("2013-05-10T00:00:00Z"), 
        "title" : "How To Avoid Duplicate Downloads In Responsive Images", 
        "url" : "http://mobile.smashingmagazine.com/2013/05/10/how-to-avoid-duplicate-downloads-in-responsive-images/", 
        "tags" : "Responsive Design" 
       }, 
       { 
        "date" : ISODate("2013-05-10T00:00:00Z"), 
        "title" : "How To Avoid Duplicate Downloads In Responsive Images", 
        "url" : "http://mobile.smashingmagazine.com/2013/05/10/how-to-avoid-duplicate-downloads-in-responsive-images/", 
        "tags" : "Techniques" 
       } 
      ], 
      "isResponsiveDesign" : 1 
     } 
    ], 
    "ok" : 1 
} 
+0

Спасибо, Джон, это помогло мне понять агрегацию немного больше. – katranci

Смежные вопросы