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】:

我不确定是否可以使用填充方法,但您可以尝试聚合管道,

$matchuser_id条件 $lookupusers 集合中的聚合管道供关注 $match以下id条件 $lookupprofilefollowing.profile $match videoURL 应该存在 $project 显示 profile 字段并使用 $arrayElemAt 获取第一个元素 $slicefollowing 中进行分页
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:带过滤的无限滚动的主要内容,如果未能解决你的问题,请参考以下文章

如何从数组中过滤数据并使用角度js应用无限滚动?

无限网格滚动和局部过滤

如果启用了无限滚动,如何防止剑道网格两次加载数据?

JavaCV开发详解之34:使用filter滤镜实现字符滚动和无限循环滚动字符叠加,跑马灯特效制作

JavaCV开发详解之34:使用filter滤镜实现字符滚动和无限循环滚动字符叠加,跑马灯特效制作

怎么实现UIpickerView的无限滚动