db.post
{user:'50001', content:...,},
{user:'50002', content:...,},
{user:'50003', content:...,},
{user:'50001', content:...,},
{user:'50002', content:...,},
db.catagory
{user:'50001', type:'public',...}
{user:'50002', type:'vip',...}
{user:'50003', type:'public',...}
我想要的是为用户发布type:public
。
我可以这样做:
publicUsers = db.catagory.distinct(user, {type:'public'})
db.post.find({user: {$in: publicUsers }}).sort({_id:-1})
或汇总使用查找。
并输出
{user:'50001', content:...,},
{user:'50003', content:...,},
{user:'50001', content:...,},
还有其他更好的方法可以更快地做到这一点吗?
考虑到大量请求的情况,我是否应该创建一个新的数据库,例如post_public来查找?
答案 0 :(得分:0)
聚合管道是您最好的选择。它非常适用于此类情况。
另一个编辑
好的,这是我最好的解决方案,但是Mongo设置了一些limitations。
首先,对未索引字段的排序操作不能使用超过100MB的RAM。
第二,在这种情况下更有意义,Mongo将单个文档的大小设置为16MB。假设您希望将帖子发布为单个数组,则在不对输出施加限制的情况下,大型数据集可以通过 。如果您决定不希望所有单个数组中的帖子,则通过删除管道的最后三个阶段($ group,$ addFields和$ project),结果将为排序后的帖子每个都在自己的文档中。如果您选择这种方式,则需要手动限制文档的数量,以获取所需的 n 个帖子。海事组织,你应该这样做。后三个阶段增加了额外的处理负担,但对输出几乎没有实际的好处。唯一的区别是迭代嵌套数组与迭代根数组。
db.categories.aggregate([
{$project: {
user: 1,
type: 1
}},
{$match: {
type: "public"
}},
{$lookup: {
from: 'posts',
localField: 'user',
foreignField: 'user',
as: 'userPosts'
}},
{$unwind: {
path: "$userPosts",
preserveNullAndEmptyArrays: false
}},
{$sort: {
"userPosts.posted": -1,
}},
{$group: {
_id: "public",
posts: {
$push: "$userPosts"
}
}},
{$addFields: {
"latestPosts": {
$slice: ["$posts", 5]
}
}},
{$project: {
posts: 0
}}
]);
您将像这样访问结果帖子:
.then(result => {
let latestPosts = result[0].latestPosts;
});
编辑
我建立了一个模拟数据库,并提出了以下解决方案:
db.categories.aggregate([{
$project: {
_id: 0,
user: 1,
type: 1,
}
}, {
$match: {
type: "public"
}
}, {
$group: {
_id: {
$concat: ["$user", "-", "$type"]
},
user: {
$first: "$user"
},
type: {
$first: "$type"
}
}
}, {
$sort: {
user: -1
}
}, {
$limit: 10
}, {
$lookup: {
from: 'posts',
localField: 'user',
foreignField: 'user',
as: 'userPosts'
}
}]);
结果将是一个对象数组,代表每个唯一的用户类型组合,并在$ match过滤器中指定类型。该对象将包含一个由该用户发布的所有帖子的子数组。所有用户都将按降序排序,并且限制为十个。
如果您只需要一个运算符就可以从类别中获得不同的值:
db.categories.aggregate([{$project: {
_id: 0,
user: 1,
type: 1
}}, {$group: {
_id: {$concat: ["$user","-","$type"]},
user: {$first: "$user"},
type: {$first: "$type"}
}}]);
目标是首先过滤掉具有非公共类型的用户,使它们不会出现在结果中,然后将属于该用户的帖子加入一个名为“ user_posts”的新字段,然后对所有用户进行排序升序。我不知道您的数据库的整个结构,因此我的具体示例可能不是最合适的,但这将是一个很好的起点。
编辑
其他一些提高大量数据性能的方法:
通过分段查询。假设您要显示分页的用户帖子。然后,您只需要查询帖子以获取当前正在查看的页面。您也可以通过预提取以下几页来减少任何明显的加载时间。
使用“虚拟”列表。这将在一个长列表中显示每个帖子,但仅获取当前正在查看或即将被查看的特定大小的块。与第一个分页示例类似。如果您熟悉Android开发中的RecyclerView,就是这样。
重组帖子在数据库中的存储方式。如果Mongo在查找特定用户或类型的帖子时不需要遍历太多不相关的数据,这将是一个更快的操作。解决方案是存储嵌套在共同祖先下方的帖子,例如其海报或视图类型。这确实意味着您可能在文档之间分散了重复的条目。这是no-SQL数据库固有的缺点之一。您将需要找到一种解决方案来处理同步分布在整个数据库中的文档。
在用于对数组进行排序的文档字段上创建新索引。索引可帮助Mongo在内部组织文档以提高搜索效率。
运行一次繁重的查询,然后$out-搜索结果。这样,您可以以比简单缓存更持久的方式存储昂贵操作的结果。
数字5的一种变体是将大型排序操作的结果输出$,然后继续在现在排序的集合的末尾插入 new 条目。
答案 1 :(得分:0)
最后,我这样做。
db.post.aggregate([
{$match:{
uid:{$in: db.catagory.distinct('id',{type:'public'})} # directly write here
_id:{$lt: ObjectId("5c6d5494b9f43f020d4122a0")} # for turn the page
}},
{$sort:{_id:-1}}, # sort by post _id
{$limit:20} # page size
])
比查找或其他方法更快。