2017-10-15 95 views
5

狐狸需要时间来解释从头到尾发生的事情。填充以下用户猫鼬

序言

用户在如下等10人。当用户A登录时,来自10个人中的每个人的X个帖子被拉入视野。

我不知道这是否是正确的做法,并会欣赏更好的做法。但是,我想尝试一下,但它不起作用。

后续型号

let mongoose = require('mongoose'); 
let Schema = mongoose.Schema; 

let FollowSchema = new Schema({ 
    user: { 
    type: Schema.Types.ObjectId, 
    ref: 'User' 
    }, 
    followers: [{ 
    type: Schema.Types.ObjectId, 
    ref: 'Card' 
    }], 
    following: [{ 
    type: Schema.Types.ObjectId, 
    ref: 'Card' 
    }] 
}); 

module.exports = mongoose.model('Follow', FollowSchema); 

卡型号

let mongoose = require('mongoose'); 
let Schema = mongoose.Schema; 

let CardSchema = new Schema({ 
    title: String, 
    content: String, 
    createdById: { 
    type: Schema.Types.ObjectId, 
    ref: 'User' 
    }, 
    createdBy: { 
    type: String 
    } 
}); 

module.exports = mongoose.model('Card', CardSchema); 

按照逻辑

当用户A如下用户B,做两件事情:

  • 推B的USER_ID到用户现场 '以下'(A是以下B)A至用户B的文档对字段 '跟随'
  • 推USER_ID(B之后是A)

    文档
    router.post('/follow', utils.loginRequired, function(req, res) { 
    const user_id = req.user._id; 
    const follow = req.body.follow_id; 
    
    let bulk = Follow.collection.initializeUnorderedBulkOp(); 
    
    bulk.find({ 'user': Types.ObjectId(user_id) }).upsert().updateOne({ 
        $addToSet: { 
         following: Types.ObjectId(follow) 
        } 
    }); 
    
    bulk.find({ 'user': Types.ObjectId(follow) }).upsert().updateOne({ 
        $addToSet: { 
         followers: Types.ObjectId(user_id) 
        } 
    }) 
    
    bulk.execute(function(err, doc) { 
        if (err) { 
         return res.json({ 
          'state': false, 
          'msg': err 
         }) 
        } 
        res.json({ 
         'state': true, 
         'msg': 'Followed' 
        }) 
    }) 
    

    })

实际DB值

> db.follows.find().pretty() 
{ 
    "_id" : ObjectId("59e3e27dace1f14e0a70862d"), 
    "user" : ObjectId("59e2194177cae833894c9956"), 
    "following" : [ 
     ObjectId("59e3e618ace1f14e0a708713") 
    ] 
} 
{ 
    "_id" : ObjectId("59e3e27dace1f14e0a70862e"), 
    "user" : ObjectId("59e13b2dca5652efc4ca2cf5"), 
    "followers" : [ 
     ObjectId("59e2194177cae833894c9956"), 
     ObjectId("59e13b2d27cfed535928c0e7"), 
     ObjectId("59e3e617149f0a3f1281e849") 
    ] 
} 
{ 
    "_id" : ObjectId("59e3e71face1f14e0a708770"), 
    "user" : ObjectId("59e13b2d27cfed535928c0e7"), 
    "following" : [ 
     ObjectId("59e3e618ace1f14e0a708713"), 
     ObjectId("59e13b2dca5652efc4ca2cf5"), 
     ObjectId("59e21942ca5652efc4ca30ab") 
    ] 
} 
{ 
    "_id" : ObjectId("59e3e71face1f14e0a708771"), 
    "user" : ObjectId("59e3e618ace1f14e0a708713"), 
    "followers" : [ 
     ObjectId("59e13b2d27cfed535928c0e7"), 
     ObjectId("59e2194177cae833894c9956") 
    ] 
} 
{ 
    "_id" : ObjectId("59e3e72bace1f14e0a708779"), 
    "user" : ObjectId("59e21942ca5652efc4ca30ab"), 
    "followers" : [ 
     ObjectId("59e13b2d27cfed535928c0e7"), 
     ObjectId("59e2194177cae833894c9956"), 
     ObjectId("59e3e617149f0a3f1281e849") 
    ] 
} 
{ 
    "_id" : ObjectId("59f0eef155ee5a5897e1a66d"), 
    "user" : ObjectId("59e3e617149f0a3f1281e849"), 
    "following" : [ 
     ObjectId("59e21942ca5652efc4ca30ab"), 
     ObjectId("59e13b2dca5652efc4ca2cf5") 
    ] 
} 
> 

使用上述数据库的结果,这是我的查询:

查询

router.get('/follow/list', utils.loginRequired, function(req, res) { 
    const user_id = req.user._id; 

    Follow.findOne({ 'user': Types.ObjectId(user_id) }) 
     .populate('following') 
     .exec(function(err, doc) { 
      if (err) { 
       return res.json({ 
        'state': false, 
        'msg': err 
       }) 
      }; 

      console.log(doc.username); 

      res.json({ 
       'state': true, 
       'msg': 'Follow list', 
       'doc': doc 
      }) 
     }) 
}); 

有了上面的查询,从我的猫鼬的一点理解填充,我期望从各拿,卡following阵列中的用户。

我的理解和期望可能是错误的,但是在这样一个终结之后,这种填充方法好吗?还是我试图解决人口聚集任务?

UPDATE:

感谢您的回答。变得非常接近,但仍然,followingCards数组不包含结果。这是我目前的Follow模型的内容:

> db.follows.find().pretty() 
{ 
    "_id" : ObjectId("59f24c0555ee5a5897e1b23d"), 
    "user" : ObjectId("59f24bda1d048d1edad4bda8"), 
    "following" : [ 
     ObjectId("59f24b3a55ee5a5897e1b1ec"), 
     ObjectId("59f24bda55ee5a5897e1b22c") 
    ] 
} 
{ 
    "_id" : ObjectId("59f24c0555ee5a5897e1b23e"), 
    "user" : ObjectId("59f24b3a55ee5a5897e1b1ec"), 
    "followers" : [ 
     ObjectId("59f24bda1d048d1edad4bda8") 
    ] 
} 
{ 
    "_id" : ObjectId("59f24c8855ee5a5897e1b292"), 
    "user" : ObjectId("59f24bda55ee5a5897e1b22c"), 
    "followers" : [ 
     ObjectId("59f24bda1d048d1edad4bda8") 
    ] 
} 
> 

以下是目前所有的内容,我从Card型号有:

> db.cards.find().pretty() 
{ 
    "_id" : ObjectId("59f24bc01d048d1edad4bda6"), 
    "title" : "A day or two with Hubtel's HTTP API", 
    "content" : "a day or two", 
    "external" : "", 
    "slug" : "a-day-or-two-with-hubtels-http-api-df77056d", 
    "createdBy" : "seanmavley", 
    "createdById" : ObjectId("59f24b391d048d1edad4bda5"), 
    "createdAt" : ISODate("2017-10-26T20:55:28.293Z"), 
    "__v" : 0 
} 
{ 
    "_id" : ObjectId("59f24c5f1d048d1edad4bda9"), 
    "title" : "US couple stole goods worth $1.2m from Amazon", 
    "content" : "for what", 
    "external" : "https://bbc.com", 
    "slug" : "us-couple-stole-goods-worth-dollar12m-from-amazon-49b0a524", 
    "createdBy" : "nkansahrexford", 
    "createdById" : ObjectId("59f24bda1d048d1edad4bda8"), 
    "createdAt" : ISODate("2017-10-26T20:58:07.793Z"), 
    "__v" : 0 
} 

与你(@Veeram)的填充虚拟实例,这里的响应我得到:

{"state":true,"msg":"Follow list","doc":{"_id":"59f24c0555ee5a5897e1b23d","user":"59f24bda1d048d1edad4bda8","following":["59f24b3a55ee5a5897e1b1ec","59f24bda55ee5a5897e1b22c"],"followers":[],"id":"59f24c0555ee5a5897e1b23d","followingCards":[]}} 

followingCards数组是空的。

使用$lookup查询,另一方面直接返回[]

我可能失去了一些东西?

+0

编辑您的架构你的问题。 – Mikey

+0

@JohnnyHK好的。会做。 – Rexford

+0

填充仅适用于在保存前将参考文件推送到Follow.following! –

回答

2

您可以使用虚拟填充或$lookup运营商在聚合管道。

使用虚拟填充

FollowSchema.virtual('followingCards', { 
    ref: 'Card', 
    localField: 'following', 
    foreignField: 'createdById' 
}); 

Follow.findOne({ 
    'user': Types.ObjectId(user_id) }) 
    .populate('followingCards') 
    .exec(function(err, doc) {  
     console.log(JSON.stringify(doc)); 
}); 

使用$lookup聚集

Follow.aggregate([ 
    { 
    "$match": { 
     "user": Types.ObjectId(user_id) 
    } 
    }, 
    { 
    "$lookup": { 
     "from": "cards", 
     "localField": "following", 
     "foreignField": "createdById", 
     "as": "followingCards" 
    } 
    } 
]).exec(function (err, doc) { 
    console.log(JSON.stringify(doc)); 
}) 
+0

感谢您的回复。尝试了你的方法。 “followingCards”数组然后是响应对象的一部分,但数组包含一个空列表。请参阅当前DB中实际值的更新问题。 – Rexford

+0

Np。你可以在文件的顶部添加'mongoose.set('debug',true);'来查看发送给mongodb的查询吗?顺便说一句,我已经修正了查找包括正确的集合名称'卡片。你是否也可以在没有匹配阶段的情况下尝试查找聚合来检查它是否有效,然后你可以放回去? – Veeram

+0

“following”集合中的“following”数组字段值在“cards”集合中没有匹配的“createdById”。尝试使用“追踪者”字段代替您提供的数据,并且可以适当调整答案。 – Veeram

0
var mongoose = require('mongoose'), Schema = mongoose.Schema 

var eventSchema = Schema({ 
title  : String, 
location : String, 
startDate : Date, 
endDate : Date 
}); 

var personSchema = Schema({ 
firstname: String, 
lastname: String, 
email: String, 
dob: Date, 
city: String, 
eventsAttended: [{ type: Schema.Types.ObjectId, ref: 'Event' }] 
}); 

var Event = mongoose.model('Event', eventSchema); 
var Person = mongoose.model('Person', personSchema); 

为了展示如何填充时,首先创建一个Person对象,

aaron = new Person({firstname: 'Aaron'}) and an event object, 
    event1 = new Event({title: 'Hackathon', location: 'foo'}): 

    aaron.eventsAttended.push(event1); 
    aaron.save(callback); 

然后,当你让你的查询,你可以填充引用这样的:

Person 
.findOne({ firstname: 'Aaron' }) 
.populate('eventsAttended') .exec(function(err, person) { 
if (err) return handleError(err); 
console.log(person); 
}); 

//只适用于将参考文献推送至person.eventsAttended