如何使用POSTS_WHERE/POSTS_JOIN创建自己的嵌套META_QUERY?

时间:2013-09-19 作者:PappApp

我的一些帖子(不是全部)有一个价格作为元键/值。今天我使用pre_get_posts 操作,以便我的用户可以搜索介于某个值之间的价格。

这是我今天使用的代码,它正在运行。

add_action(\'pre_get_posts\', \'my_search_price\');
function my_search_price( $query ) {
    if ($query->get(\'maxprice\') != "" && $query->get(\'minprice\') != "" && $query->is_main_query()) {

        $maxprice = intval($query->get(\'maxprice\'));
        $minprice = intval($query->get(\'minprice\'));

        $meta = array();
        $meta[] = 
        array (
            \'key\' => \'price\',
            \'value\' => $maxprice,
            \'compare\' => \'<=\',
            \'type\' => \'numeric\'
        );

        $meta[] = 
        array (
            \'key\' => \'price\',
            \'value\' => $minprice,
            \'compare\' => \'>=\',
            \'type\' => \'numeric\'
        );

        $meta[] = 
        array (
            \'key\' => \'price_updated\',
            \'value\' => time()-(60*60*24*14),
            \'compare\' => \'>\',
            \'type\' => \'numeric\'
        );

        $query->set(\'meta_query\', $meta);
    }
}
我的问题是,一些帖子现在有第二个价格,也存储为元键/值。新价格的名称为“price\\u used”,此价格有自己的更新键/值,名为“price\\u used\\u updated”。

我想修改函数my_search_price() 这样它也可以处理新的价格。结果应该是“price”或“price\\u used”介于minprice和maxprice之间的帖子。“price\\u updated”/“price\\u used\\u updated”最长应为14天。

正如我从其他一些帖子中了解到的,meta\\u查询不能嵌套。因此,我需要使用posts\\u join或/和posts\\u where过滤器来修改SQL。

请有人给我指出解决方案的正确方向吗?我猜我不是第一个需要更高级meta\\u查询的人。但我以前从未修改过SQL查询。

我所做的就是阅读这些页面:

更新:结果查询应如下所示:

SELECT SQL_CALC_FOUND_ROWS wp_posts.*, mtGP2.meta_value, mtAM2.meta_value
FROM wp_posts

INNER JOIN wp_postmeta AS mtGP1 ON (wp_posts.ID = mtGP1.post_id)
INNER JOIN wp_postmeta AS mtGP2 ON (wp_posts.ID = mtGP2.post_id)

INNER JOIN wp_postmeta AS mtAM1 ON (wp_posts.ID = mtAM1.post_id)
INNER JOIN wp_postmeta AS mtAM2 ON (wp_posts.ID = mtAM2.post_id)

WHERE 1=1

AND wp_posts.post_type = \'post\'
AND wp_posts.post_status = \'publish\'

AND
(
(mtGP1.meta_key = \'price\' AND CAST(mtGP1.meta_value AS SIGNED) BETWEEN 1 AND 10
AND mtGP2.meta_key = \'price_updated\' AND CAST(mtGP2.meta_value AS SIGNED) > NOW()-60*60*24*14)
OR
(mtAM1.meta_key = \'price_used\' AND CAST(mtAM1.meta_value AS SIGNED) BETWEEN 1 AND 10
AND mtAM2.meta_key = \'price_used_updated\' AND CAST(mtAM2.meta_value AS SIGNED) > NOW()-60*60*24*14)
)
GROUP BY wp_posts.ID
但是这个查询有两个问题。

1) 速度很慢

2) 我仍然有一个问题,因为我不知道如何在wordpress中实现查询。我想我需要使用post\\u where和posts\\u join过滤器,但我不确定如何使用。

更新2。我已经重写了查询,所以它不再慢了。但我仍然不知道如何使用过滤器或操作(如我原来的my\\u search\\u price()函数)在wordpress中实现查询。

SELECT SQL_CALC_FOUND_ROWS *
  FROM
(
SELECT wp_posts.*
FROM wp_posts
INNER JOIN wp_postmeta AS mtGP1 ON (wp_posts.ID = mtGP1.post_id)
INNER JOIN wp_postmeta AS mtGP2 ON (wp_posts.ID = mtGP2.post_id)
WHERE 1=1
AND wp_posts.post_type = \'post\'
AND wp_posts.post_status = \'publish\'
AND mtGP1.meta_key = \'price\'
AND CAST(mtGP1.meta_value AS SIGNED) BETWEEN 1 AND 10
AND mtGP2.meta_key = \'app_updated\'
AND CAST(mtGP2.meta_value AS SIGNED) > UNIX_TIMESTAMP()-60*60*24*14
GROUP BY wp_posts.ID

UNION

SELECT wp_posts.*
FROM wp_posts
INNER JOIN wp_postmeta AS mtGP1 ON (wp_posts.ID = mtGP1.post_id)
INNER JOIN wp_postmeta AS mtGP2 ON (wp_posts.ID = mtGP2.post_id)
WHERE 1=1
AND wp_posts.post_type = \'post\'
AND wp_posts.post_status = \'publish\'
AND mtGP1.meta_key = \'price_used\'
AND CAST(mtGP1.meta_value AS SIGNED) BETWEEN 1 AND 10
AND mtGP2.meta_key = \'price_used_updated\'
AND CAST(mtGP2.meta_value AS SIGNED) > UNIX_TIMESTAMP()-60*60*24*14
GROUP BY wp_posts.ID
) AS t

1 个回复
SO网友:s_ha_dum

以下是您将如何进行UNION 使用WP_Query.

add_filter(
  \'posts_request\',
  function ($clauses) {

    $clauses = str_replace(\'SQL_CALC_FOUND_ROWS\',\'\',$clauses,$scfr);

    $scfr = (0 < $scfr) : \'SQL_CALC_FOUND_ROWS\' : \'\';

    $clause2 = $clauses; // manipulate this

    return "SELECT {$scfr} u.* FROM (({$clauses}) UNION ({$clause2})) as u";
  },
  1,
  2
);
设置您的WP_Query 用于生成UNION 然后操纵它来创建整个查询。像这样的事情应该很接近。

add_action(\'pre_get_posts\', \'my_search_price\');
function my_search_price( $query ) {
    if ($query->get(\'maxprice\') != "" && $query->get(\'minprice\') != "" && $query->is_main_query()) {

        $maxprice = intval($query->get(\'maxprice\'));
        $minprice = intval($query->get(\'minprice\'));

        $meta = array();

        $meta[] =
          array (
              \'key\' => \'price\',
              \'value\' => array($maxprice,$minprice),
              \'compare\' => \'between\',
          );

        $meta[] = 
          array (
              \'key\' => \'app_updated\',
              \'value\' => time()-(60*60*24*14),
              \'compare\' => \'>\',
              \'type\' => \'numeric\'
          );

        $query->set(\'meta_query\', $meta);
    }
}

add_filter(
  \'posts_request\',
  function ($clauses) {

    $clauses = str_replace(\'SQL_CALC_FOUND_ROWS\',\'\',$clauses,$scfr);

    $scfr = (0 < $scfr) ? \'SQL_CALC_FOUND_ROWS\' : \'\';

    $clause2 = str_replace(\'price\',\'price_used\',$clauses); // manipulate this
    $clause2 = str_replace(\'app_updated\',\'price_used_updated\',$clauses);

    return "SELECT {$scfr} u.* FROM (({$clauses}) UNION ({$clause2})) as u";
  },
  1,
  2
);
您需要将逻辑添加到post_requests 过滤,使其在不希望运行时不会运行。

结束

相关推荐

使用新的WP-Query()从循环中过滤后期格式;

嗨,我目前正在为我的博客构建一个主题。下面的代码指向最新的帖子(特色帖子)。因为这将有一个不同的风格比所有其他职位。然而我想过滤掉帖子格式:链接使用我在循环中定义的WP查询,因为它给我带来了更多的灵活性。我该怎么做呢? <?php $featured = new WP_Query(); $featured->query(\'showposts=1\'); ?> <?php while ($featured->have_post