Mongoose / mongo多对多计算字段

时间:2016-03-10 10:10:28

标签: mongodb mongoose

这是我的架构。每个用户都有很多帖子,每个帖子都有收藏它的用户列表。

var User = mongoose.model('User', {
  name: String,
  posts: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Post' }]
});

var Post = mongoose.model('Post', {
  name: String,
  favorited: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }]
});

我需要选择所有带有布尔标志的用户帖子是否有用。

我开始时:

User.findById('56e14680476f47200f1f598e')
  .populate('posts')
 .then(u => {
  console.log(u);
})
.catch(console.error.bind(console));

输出:

   [ { favorited: [Object],
       __v: 0,
       name: 'post 1',
       _id: 56e14680476f47200f1f5991 },
     { favorited: [],
       __v: 0,
       name: 'post 2',
       _id: 56e14680476f47200f1f5992 },
     { favorited: [],
       __v: 0,
       name: 'post 3',
       _id: 56e14680476f47200f1f5993 } ],
  __v: 0,
  name: 'user 1',
  _id: 56e14680476f47200f1f598e }

聚合,map-reduce或者可能重新设计架构?也许有复杂结构的好例子?在哪里挖?

1 个答案:

答案 0 :(得分:1)

请尝试这个

User.findById('56e14680476f47200f1f598e')
    .populate('posts')
    .exec(function(err, user) {
        if (err)
            console.log(err);
        else{
            // populate `posts` again
            Post.populate(user.posts, {path:'favorited', model: 'User'}, function(err, ret) {
                if (err)
                    console.log(err);
                else
                    console.log(require('util').inspect(ret, { showHidden: true, depth: null }));
            })
        }
    });

第二个想法,如果User集合中有垃圾字段,您可以将user信息嵌套到Post集合中,而不是引用它。

var Post = mongoose.model('Post', {
  name: String,
  favorited: [{ name: String,
                // other fields... 
              }]
});

一个值得关注的问题是,如果有许多受欢迎的用户可能会使Post集合过大。确保不再有收集限制, 16兆字节

无论如何,数据模式应该满足您的数据,并便于查询。