填充以下用户猫鼬
Posted
技术标签:
【中文标题】填充以下用户猫鼬【英文标题】:populate following users mongoose 【发布时间】:2018-03-27 10:06:21 【问题描述】:让我花时间解释从头到尾发生的事情。
序言:
用户 a 关注了另外 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 推送到字段 'following' 上的用户 A 文档(A 跟随 B)将 A 的 user_id 推送到字段“followers”上的用户 B 文档(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.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
)
)
);
通过上述查询,根据我对 Mongoose 填充的一点了解,我希望从 following
数组中的每个用户那里获得卡片。
我的理解和期望可能是错误的,但是有了这样的最终目标,这种填充方法可以吗?还是我试图解决人口聚合任务?
更新:
感谢您的回答。非常接近,但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
Model 获得的所有当前内容:
> 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
查询只返回[]
我可能错过了什么?
【问题讨论】:
用你的模式编辑你的问题。 @JohnnyHK 好的。会的。 populate 仅在保存前将 refs 推送到 Follow.following 时才有效! 【参考方案1】:您可以在聚合管道中使用虚拟填充或$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));
)
【讨论】:
感谢您的回复。试过你的方法。followingCards
数组是响应对象的一部分,但是该数组包含一个空列表。请查看当前数据库中实际值的更新问题。
Np。您可以在文件顶部添加 mongoose.set('debug', true);
以查看发送到 mongodb 的查询吗?顺便说一句,我已修复查找以包含正确的集合名称cards
。您是否也可以尝试不使用匹配阶段的查找聚合来检查它是否有效,然后您可以将其放回原处?
follows
集合中的following
数组字段值在cards
集合中没有匹配的createdById
。尝试使用 followers
字段代替您提供的数据,您可以适当地调整答案。【参考方案2】:
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);
为了展示如何使用填充,首先创建一个人对象,
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);
);
// 仅当我们将 refs 推送到 person.eventsAttended 时才有效
【讨论】:
【参考方案3】:注意:将 Activity.find 更改为 Card.find
const ObjectID = require("mongodb");
// import Follow and Activity(Card) schema
const userId = req.tokenData.userId; // edit this too...
Follow.aggregate([
$match:
user: ObjectID(userId)
])
.then(data =>
// console.log(data)
var dataUsers = data[0].following.map(function(item)
return item._id;
);
// console.log(dataUsers)
Activity.find(
createdById: $in: dataUsers ,
_id: 1,
title: 1,
content: 1,
createdBy: 1,
creatorAvatar: 1,
activityType: 1,
createdAt: 1
)
// .sort(createdAt:-1)
.then(posts => res.send( posts ));
);
【讨论】:
以上是关于填充以下用户猫鼬的主要内容,如果未能解决你的问题,请参考以下文章