【问题标题】:Laravel Entity Attribute Value Filter Multipe AttributesLaravel 实体属性值过滤器多重属性
【发布时间】:2021-01-22 11:20:27
【问题描述】:

我正在尝试开发一个与 postmeta 模型具有一对多关系的 post 模型(包括 idpost_idmeta_keymeta_value 列)并且还具有多对多关系与术语模型的许多关系(包括term_id 和其他一些列,以及包括idpost_postIdterm_term_term_id 列的post_term 表)。

我创建了一个表单,其中包含一些 post_metas 和术语,用于搜索和过滤我的帖子。

这个示例 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` = ?)

我可以从此查询中获得正确的结果,但查询执行速度太慢,这是我的主要问题。有什么替代方法吗?

【问题讨论】:

  • 如果你有更多的记录,尽量不要使用 whereHas。如果您真的想使用 whereHas,请添加索引。我之前遇到过同样的问题,我使用了联接。
  • 您好,感谢您的评论,您能再解释一下吗?或者只是与我分享一个如何做的例子?

标签: php mysql laravel eloquent entity-attribute-value


【解决方案1】:

您可以使用带有聚合的单个连接查询来过滤每个帖子的元属性

$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部分是关键,它将有条件地过滤掉与元信息不匹配的帖子,

【讨论】:

    【解决方案2】:

    试试这个代码,不确定它是否有效,希望你能明白。

            $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);
                }
            });
    

    【讨论】:

    • 感谢您的回复,但此查询不能解决我的问题。当我加入表格时,每一行都有一个 meta_key,所以当我使用“and”来调查不同的 meta_keys 时,没有任何行具有例如 meta_key=a 和 meta_key=b。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-17
    • 2012-02-24
    相关资源
    最近更新 更多