我试图了解 mongodb 和 laravel 的更高级功能,但遇到了麻烦。目前我的架构设置是users
, posts
, and posts_votes
收藏。这posts_votes
has a user_id
, post_id
and timestamp
field.
在关系数据库中,我只需离开加入posts_votes
收集、计数并按计数排序。需要时排除日期等等。
MongoDB 我遇到了困难,因为没有左连接等效项。所以我想学习如何以更加文档化的方式实现我的目标。
On my Post
Laravel 中的模型,我是这样引用的。因此,查看单个帖子,我可以获得投票数,查看当前用户是否投票给特定帖子等。
public function votes()
{
return $this->hasMany(PostVote::class, 'post_id');
}
我当前的工作查询如下所示:
$posts = Post::forCategoryType($type)
->with('votes', 'author', 'businessType')
->where('approved', true)
->paginate(25);
The forCategoryType
方法只是我添加的扩展范围。这是在Post
模型/文档类。
public function scopeForCategoryType($builder, $catType)
{
if ($catType->exists) {
return $builder->where('cat_id', $catType->id);
}
return $builder;
}
所以当我看像这样的帖子 https://stackoverflow.com/questions/11312419/mongodb-schema-design-voting-on-posts,它接近我想要完成的目标,但我没有正确应用它。例如,我将主查询更改为如下所示:
$posts = Post::forBusinessType($type)
->with('votes', 'author', 'businessType')
->where('approved', true)
->sortByVotes()
->paginate(25);
并创建了这个新方法Post
model:
public function scopeSortByVotes($builder, $dir = 'desc')
{
return $builder->raw(function($collection) {
return $collection->aggregate([
['$group' => [
'_id' => ['post_id' => 'votes.$post_id', 'user_id' => 'votes.$user_id']
],
'vote_count' => ['$sum' => 1]
],
['$sort' => ['vote_count' => -1]]
]);
});
}
这会返回错误exception: A pipeline stage specification object must contain exactly one field.
不知道如何解决这个问题(仍在寻找),所以我尝试了:
return $collection->aggregate([
['$unwind' => '$votes'],
['$group' => [
'_id' => ['post_id' => ['$votes.post_id', 'user_id' => '$votes.user_id']],
'count' => ['$sum' => 1]
]
]
]);
返回一个空的ArrayIterator
,所以我尝试了:
public function scopeSortByVotes($builder, $dir = 'desc')
{
return $builder->raw(function($collection) {
return $collection->aggregate([
'$lookup' => [
'from' => 'community_posts_votes',
'localField' => 'post_id',
'foreignField' => '_id',
'as' => 'vote_count'
]
]);
});
}
但在这种设置下,我只是得到未排序的帖子列表。在版本 3.2.8 上。
默认加载最新的所有内容。但最终我希望能够根据这些帖子一生获得的票数来提取这些帖子,同时也根据哪些帖子在上周、上个月等获得最多票数进行查询。
我分享的那个例子将总计链接在Post
模型和所有对其进行投票的用户 ID 的数组。我使用一个单独的集合来设置事物的方式user_id
, post_id
以及投票发生的时间戳,我还能实现同样的目标吗?
注意:使用这个Laravel MongoDB 库 https://github.com/jenssegers/laravel-mongodb.