Mongoose:带过滤的无限滚动
Posted
技术标签:
【中文标题】Mongoose:带过滤的无限滚动【英文标题】:Mongoose: Infinite scroll with filtering 【发布时间】:2021-07-05 04:43:06 【问题描述】:我有这两个模型:
用户.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":
,
"profile":
"videoURL":"video_url_6"
]
我正在尝试实现连接用户跟随的用户视频的无限滚动。
这意味着,我必须过滤 user.following.profile.videoURL videoURL 存在于何处
假设,我将通过两个视频加载两个视频:
响应 1:["video_url_1","video_url_2"] 响应 2:["video_url_3","video_url_4"] 响应 3:["video_url_5","video_url_6"]通常,无限滚动很容易,因为我必须按存储顺序 2 x 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
所以我想,我没有办法使用填充来过滤基于user.followers
,基于每个user.follower.profile.videoURL
【问题讨论】:
你能解释一下你想做什么样的过滤吗? 我的错,我将不得不过滤 user.following.profile.videoURL WHERE videoURL 存在 【参考方案1】:所以你想要的是无限滚动的表格和:
您可以选择给定的方法来解决您的问题:
-
将数据(第一页)加载到网格中。
在列上设置过滤器。
再次加载数据,这次使用过滤器。
【讨论】:
我没明白你的意思。【参考方案2】:我不确定是否可以使用填充方法,但您可以尝试聚合管道,
$match
user_id
条件
$lookup
与 users
集合中的聚合管道供关注
$match
以下id条件
$lookup
与 profile
为 following.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]
])
Playground
建议:
您可以改进架构设计,
删除配置文件架构并在用户集合中添加配置文件对象,因此您可以使用填充方法轻松实现您的要求, 将匹配条件放在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,
);
【讨论】:
您发布的内容可以通过填充来实现。问题是当我在 profile.videoURL 上添加过滤时,我没有找到使用填充的方法。而且你没有在你的聚合解决方案中提到它。 我告诉过你这是过滤条件“user.following.profile.videoURL WHERE videoURL exists”。我认为您提出的建议将从以下数组返回前两个用户,并且只会使用过滤条件填充配置文件,然后是后两个用户,依此类推。但是,我只希望它从以下数组中返回用户 WHERE following.profile.videoURL EXISTS。 我查看了使用填充但不可能,我已根据您的填充查询更新了聚合查询。 我已经添加了一个建议,如果您只是计划并开始您的开发,您可以改进这些东西,nosql 规则是避免更多的收集,尽量管理更少的收集。并避免加入。 很抱歉,我真的没有得到你的建议以及它如何适用于这里。以上是关于Mongoose:带过滤的无限滚动的主要内容,如果未能解决你的问题,请参考以下文章
JavaCV开发详解之34:使用filter滤镜实现字符滚动和无限循环滚动字符叠加,跑马灯特效制作