Laravel 实体属性值过滤多个属性
Laravel Entity Attribute Value Filter Multipe Attributes
我正在尝试开发一个 post 模型,它与 post 元模型(包括 id
、post_id
、meta_key
, meta_value
列)也和term model 有多对多的关系(包括term_id
和其他一些列,还有post_term table 包括id
、post_postId
、term_term_term_id
列)。
我创建了一个表单,其中包含一些 post_metas 和搜索和过滤我的 post 的术语。
此示例 PHP 代码突出显示了我使用的内容:
$posts_query = Post::where('post_type', 'add')->where('author', Auth::id())->where(function ($q0) use($filter_metas){
foreach ($filter_metas as $index => $meta) {
$q0->whereHas('postmetas', function ($q0) use ($index,$meta) {
$q0->where('meta_key', $index)->where('meta_value', $meta);
});
}
});
这是获取结果的执行查询。
select * from `posts` where `post_type` = ? and `author` = ? and (exists (select * from `postmeta` where `posts`.`postId` = `postmeta`.`post_id` and `meta_key` = ?) and exists (select * from `postmeta` where `posts`.`postId` = `postmeta`.`post_id` and `meta_key` = ? and `meta_value` in (?, ?, ?, ?)) and exists (select * from `postmeta` where `posts`.`postId` = `postmeta`.`post_id` and `meta_key` = ? and `meta_value` in (?, ?, ?)) and exists (select * from `postmeta` where `posts`.`postId` = `postmeta`.`post_id` and `meta_key` = ? and `meta_value` > ?) and exists (select * from `postmeta` where `posts`.`postId` = `postmeta`.`post_id` and `meta_key` = ? and `meta_value` = ?) and exists (select * from `postmeta` where `posts`.`postId` = `postmeta`.`post_id` and `meta_key` = ? and `meta_value` = ?) and exists (select * from `postmeta` where `posts`.`postId` = `postmeta`.`post_id` and `meta_key` = ? and `meta_value` = ?) and exists (select * from `postmeta` where `posts`.`postId` = `postmeta`.`post_id` and `meta_key` = ? and `meta_value` = ?) and exists (select * from `postmeta` where `posts`.`postId` = `postmeta`.`post_id` and `meta_key` = ? and `meta_value` = ?) and exists (select * from `postmeta` where `posts`.`postId` = `postmeta`.`post_id` and `meta_key` = ? and `meta_value` = ?)
我可以从这个查询中得到正确的结果,但是查询执行得太慢,这是我的主要问题。是否有任何替代方法?
试试这个代码,不确定它是否有效,希望你能明白。
$posts_query = Post::where('post_type', 'add')
->where('author', Auth::id())
->leftJoin('postmeta', function($join){
$join->on('posts.postId', 'postmeta.post_id');
})
->where(function ($query) use ($filter_metas) {
foreach ($filter_metas as $index => $meta) {
$query->where('postmeta.meta_key', $index)
->where('postmeta.meta_value', $meta);
}
});
您可以使用带有聚合的单个连接查询来过滤每个 post
的元属性
$posts = Post::select(['posts.postId','posts.name'])
->where('post_type', 'add')
->where('author', Auth::id())
->join('postmeta', 'posts.postId', '=', 'postmeta.post_id')
->groupBy('posts.postId','posts.name')
->where(function ($query) use ($filter_metas) {
foreach ($filter_metas as $index => $meta) {
$query->havingRaw('sum(case when meta_key = ? and meta_value = ? then 1 else 0 end) > 0', [$index, $meta]);
}
});
在上面的查询中havingRaw
部分是关键它会条件性地过滤掉post与元信息不匹配的,
我正在尝试开发一个 post 模型,它与 post 元模型(包括 id
、post_id
、meta_key
, meta_value
列)也和term model 有多对多的关系(包括term_id
和其他一些列,还有post_term table 包括id
、post_postId
、term_term_term_id
列)。
我创建了一个表单,其中包含一些 post_metas 和搜索和过滤我的 post 的术语。
此示例 PHP 代码突出显示了我使用的内容:
$posts_query = Post::where('post_type', 'add')->where('author', Auth::id())->where(function ($q0) use($filter_metas){
foreach ($filter_metas as $index => $meta) {
$q0->whereHas('postmetas', function ($q0) use ($index,$meta) {
$q0->where('meta_key', $index)->where('meta_value', $meta);
});
}
});
这是获取结果的执行查询。
select * from `posts` where `post_type` = ? and `author` = ? and (exists (select * from `postmeta` where `posts`.`postId` = `postmeta`.`post_id` and `meta_key` = ?) and exists (select * from `postmeta` where `posts`.`postId` = `postmeta`.`post_id` and `meta_key` = ? and `meta_value` in (?, ?, ?, ?)) and exists (select * from `postmeta` where `posts`.`postId` = `postmeta`.`post_id` and `meta_key` = ? and `meta_value` in (?, ?, ?)) and exists (select * from `postmeta` where `posts`.`postId` = `postmeta`.`post_id` and `meta_key` = ? and `meta_value` > ?) and exists (select * from `postmeta` where `posts`.`postId` = `postmeta`.`post_id` and `meta_key` = ? and `meta_value` = ?) and exists (select * from `postmeta` where `posts`.`postId` = `postmeta`.`post_id` and `meta_key` = ? and `meta_value` = ?) and exists (select * from `postmeta` where `posts`.`postId` = `postmeta`.`post_id` and `meta_key` = ? and `meta_value` = ?) and exists (select * from `postmeta` where `posts`.`postId` = `postmeta`.`post_id` and `meta_key` = ? and `meta_value` = ?) and exists (select * from `postmeta` where `posts`.`postId` = `postmeta`.`post_id` and `meta_key` = ? and `meta_value` = ?) and exists (select * from `postmeta` where `posts`.`postId` = `postmeta`.`post_id` and `meta_key` = ? and `meta_value` = ?)
我可以从这个查询中得到正确的结果,但是查询执行得太慢,这是我的主要问题。是否有任何替代方法?
试试这个代码,不确定它是否有效,希望你能明白。
$posts_query = Post::where('post_type', 'add')
->where('author', Auth::id())
->leftJoin('postmeta', function($join){
$join->on('posts.postId', 'postmeta.post_id');
})
->where(function ($query) use ($filter_metas) {
foreach ($filter_metas as $index => $meta) {
$query->where('postmeta.meta_key', $index)
->where('postmeta.meta_value', $meta);
}
});
您可以使用带有聚合的单个连接查询来过滤每个 post
的元属性$posts = Post::select(['posts.postId','posts.name'])
->where('post_type', 'add')
->where('author', Auth::id())
->join('postmeta', 'posts.postId', '=', 'postmeta.post_id')
->groupBy('posts.postId','posts.name')
->where(function ($query) use ($filter_metas) {
foreach ($filter_metas as $index => $meta) {
$query->havingRaw('sum(case when meta_key = ? and meta_value = ? then 1 else 0 end) > 0', [$index, $meta]);
}
});
在上面的查询中havingRaw
部分是关键它会条件性地过滤掉post与元信息不匹配的,