如何解决Mongoose:带过滤的无限滚动
我有这两个模型:
User.js
const UserSchema = new Schema({
profile: {
type: Schema.Types.ObjectId,ref: "profiles",},following: [
{
type: Schema.Types.ObjectId,ref: "users",],});
module.exports = User = mongoose.model("users",UserSchema);
Profile.js
const ProfileSchema = new Schema({
videoURL: {
type: String,});
module.exports = Profile = mongoose.model("profiles",ProfileSchema);
以下是 User
文档的示例:
{
"following": [
{
"profile":{
"videoURL":"video_url_1"
}
},{
"profile":{
"videoURL":"video_url_2"
}
},{
"profile":{}
},{
"profile":{
"videoURL":"video_url_3"
}
},{
"profile":{
"videoURL":"video_url_4"
}
},{
"profile":{
"videoURL":"video_url_5"
}
},{
"profile":{
"videoURL":"video_url_6"
}
}
]
}
这意味着,我将不得不过滤 user.following.profile.videoURL WHERE videoURL 存在
假设,我将通过两个视频加载两个视频:
- 响应 1:["video_url_1","video_url_2"]
- 响应 2:["video_url_3","video_url_4"]
- 响应 3:["video_url_5","video_url_6"]
通常,无限滚动很容易,因为我必须按存储顺序 2 到 2 加载文档,而无需对任何字段进行过滤。
示例:无限滚动显示两个两个被关注的用户
User.findById(user_id).populate({
path: "following",options: {
skip: 2 * page,limit: 2,});
但是,现在我必须对每个 follow_user.profile.video 执行过滤,然后两个两个地返回。而且我看不到如何同时执行BOTH过滤和无限滚动。
注意:根据documentation:
通常,无法根据故事作者的属性使 populate() 过滤故事。例如,即使填充了作者,以下查询也不会返回任何结果。
const story = await Story.
findOne({ 'author.name': 'Ian Fleming' }).
populate('author').
exec();
story; // null
所以我想,我无法使用 populate 来过滤基于 user.followers
的 user.follower.profile.videoURL
,基于每个 const logout = async (req,res) => {
const refToken = req.body.refreshToken;
try {
const payload = jwt.verify(refToken,process.env.REFRESH_TOKEN_SECRET);
req.user = payload.user;
// Verify that the token matches the token in redis
const getResult = redis.GET(req.user,(err,result) => {
if (err) {
console.error(err.message);
return res.status(500).send('Server Error');
}
if (refToken !== result) {
return res.status(401).send('Not Authorized');
}
console.log(result);
return result;
});
const deleted = await redis.DEL(req.user,result) => {
console.log('executed');
if (err) {
console.error(err.message);
return res.status(500).send('Server Error');
}
return result;
});
if (deleted === 1) {
return res.status(401).json('User has been logged out');
}
} catch (err) {
console.error(err.message);
if (err.message === 'jwt expired') {
return res.status(401).json({ error: 'Token expired' });
}
return res.status(500).send('Server Error');
}
};
解决方法
所以你想要的是无限滚动的表格和:
您可以选择给定的方法来解决您的问题:
- 将数据(第一页)加载到网格中。
- 在列上设置过滤器。
- 再次加载数据,这次使用过滤器。
我不确定 populate 方法是否可行,但您可以尝试聚合管道,
-
$match
user_id
条件 -
$lookup
在users
集合中带有聚合管道以供关注 -
$match
以下 id 条件 -
$lookup
withprofile
forfollowing.profile
-
$match
videoURL
应该存在 -
$project
显示profile
字段并使用$arrayElemAt
获取第一个元素
-
$slice
在following
中进行分页
let page = 0;
let limit = 2;
let skip = limit * page;
User.aggregate([
{ $match: { _id: mongoose.Types.ObjectId(user_id) } },{
$lookup: {
from: "users",let: { following: "$following" },pipeline: [
{ $match: { $expr: { $in: ["$_id","$$following"] } } },{
$lookup: {
from: "profiles",localField: "profile",foreignField: "_id",as: "profile"
}
},{ $match: { "profile.videoURL": { $exists: true } } },{
$project: {
profile: { $arrayElemAt: ["$profile",0] }
}
}
],as: "following"
}
},{
$addFields: {
following: {
$slice: ["$following",skip,limit]
}
}
}
])
建议:
您可以改进架构设计,
- 删除配置文件架构并在用户集合中添加配置文件对象,因此您可以使用 populate 方法轻松实现您的要求,
- 将匹配条件放入以下填充
videoURL
存在
const UserSchema = new Schema({
profile: {
type: {
videoURL: {
type: String
}
}
},following: [
{
type: Schema.Types.ObjectId,ref: "users"
}
]
});
module.exports = User = mongoose.model("users",UserSchema);
User.findById(user_id).populate({
path: "following",match: {
"profile.videoURL": { $ne: null }
},options: {
skip: 2 * page,limit: 2,}
});
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。