$ project基于元素的新布尔字段存在于子文档的数组中

时间:2013-05-12 21:41:02

标签: mongodb

我有一系列博客,其中的帖子嵌入到:

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 个答案:

答案 0 :(得分:1)

我唯一可以把它想象成聚合的方式结果是啰嗦。将查询建模为map-reduce操作可能更容易/更简单。无论如何,我们走了:

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
}