我认为问题本质上与sql查询结构有关,我不是专家。。。。
我需要通过2个参数搜索帖子(自定义帖子类型):
pd\\U市
pd\\U国家
请注意,meta\\u查询关系是“或”,所以如果上面两个中的任何一个是类似的,我们应该有一些结果。
第三个键(is\\U赞助)用于对帖子进行排序!它可以是1或0,“is\\u赞助商”值等于1的帖子应列在顶部。
下面是WordPress的事情:
$sfp_query_args = array(
\'sfp_complex_search\' => \'yeap\',
\'tax_query\' => array( array( \'taxonomy\' => \'sfp_post_category\', \'terms\' => $term_id ) ),
//\'meta_key\' => \'is_sponsored\',
\'post_type\' => \'sfpposts\',
\'post_status\' => \'publish\',
\'showposts\' => (int)$per_page,
\'paged\' => $paged,
\'meta_query\' => array( \'relation\' => \'OR\',
array( \'key\' => \'pd_city\', \'value\' => $sfp_search_meta, \'compare\' => \'LIKE\' ),
array( \'key\' => \'pd_country\', \'value\' => $sfp_search_meta, \'compare\' => \'LIKE\' ),
array( \'key\' => \'is_sponsored\' )
)
);
$sfp_search = new WP_Query( $sfp_query_args );
我还需要使用“posts\\u orderby”筛选结果,以便让赞助商排名靠前:
add_filter( \'posts_orderby\', \'sfp_modify_search\' );
function sfp_modify_search( $orderby ) {
if( !is_admin() && is_page( $this->options[ \'sfp_page_entries_search\' ] ) ) {
global $wpdb;
$orderby = " CASE WHEN mt2.meta_value = 0 THEN 1 END, $wpdb->posts.post_date DESC ";
}
return $orderby;
}
真正的问题在于,通过此查询,将返回“sfp\\U post\\u category”中的所有帖子,而不仅仅是那些与“pd\\u city”或“pd\\u country”匹配的帖子,因为所有帖子都有“is\\u-Conspondered”元键(值设置为1或0)。再次强调:“is\\U赞助”用于排序!
当var\\u转储时
var_dump( $sfp_search->request );
。。。WordPress的sql如下所示:
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
INNER JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id)
INNER JOIN wp_postmeta AS mt2 ON (wp_posts.ID = mt2.post_id)
WHERE 1=1
AND ( wp_term_relationships.term_taxonomy_id IN (77) )
AND wp_posts.post_type = \'sfpposts\'
AND (wp_posts.post_status = \'publish\')
AND ( (wp_postmeta.meta_key = \'pd_city\'
AND CAST(wp_postmeta.meta_value AS CHAR)
LIKE \'%something%\')
OR (mt1.meta_key = \'pd_country\'
AND CAST(mt1.meta_value AS CHAR)
LIKE \'%something%\')
OR mt2.meta_key = \'is_sponsored\' )
GROUP BY wp_posts.ID
ORDER BY CASE WHEN mt2.meta_value = 0 THEN 1 END, wp_posts.post_date DESC
LIMIT 0, 10
如何从结果中删除所有与“pd\\U城市”或“pd\\U国家”不匹配的帖子?
最合适的回答,由SO网友:Johannes Pille 整理而成
罪魁祸首是元查询不支持不同和/或嵌套关系,顺便说一下,这是一个缺点,以前也让我发疯了。在最近的一个实例中,还有一个搜索场景。
你想做的事根本无法用WP_Query
以及一个回路
您似乎已经注意到,是否将排序键放置在meta_query
数组或其外部作为常规查询参数并没有什么区别。如果将元查询关系设置为OR
并指定meta_key
查询参数的任意位置,而不设置伴随的meta_value
参数,查询将始终至少返回设置了meta\\u键的所有帖子
顺便提一下,为了完整性:当您使用单个meta\\u查询时!=
作为的值meta_compare
, 查询将返回所有结果meta_key
设置且不等于给定值meta_value
- 它不会返回任何没有meta_key
根本不用。元查询失败的另一点。
解决方案1我看到两种选择。首先,您可以省略is_sponsored
从查询中删除meta键,同时省略分页,获取正确的帖子并使用第二个实例进行排序WP_Query
, 通过post__in
参数:
$sfp_search_args = array(
\'sfp_complex_search\' => \'yeap\',
\'tax_query\' => array( array( \'taxonomy\' => \'sfp_post_category\', \'terms\' => $term_id ) ),
\'post_type\' => \'sfpposts\',
\'post_status\' => \'publish\',
\'meta_query\' => array(
\'relation\' => \'OR\',
array( \'key\' => \'pd_city\', \'value\' => $sfp_search_meta, \'compare\' => \'LIKE\' ),
array( \'key\' => \'pd_country\', \'value\' => $sfp_search_meta, \'compare\' => \'LIKE\' )
)
);
$sfp_search = new WP_Query( $sfp_search_args );
$post_ids = array();
while ( $sfp_search->have_posts() ) : $sfp_search->next_post();
$post_ids[] = $sfp_search->post->ID;
endwhile;
$sfp_ordered_args(
\'post__in\' => $post_ids,
// note that \'showposts\' is deprected
\'posts_per_page\' => (int)$per_page,
\'paged\' => $paged,
\'meta_key\' => \'is_sponsored\',
\'order\' => \'DESC\',
\'orderby\' => \'meta_value_num date\'
);
$sfp_ordered = new WP_Query( $sfp_ordered_args );
while ( $sfp_ordered->have_posts() ) : $sfp_ordered->next_post();
// display posts
endwhile;
请注意
$orderby
参数
WP_Query
将采用由空格分隔的多个值。您的搜索修改可能过于复杂。
解决方案2,因为我喜欢您的var\\u转储查询对象request
属性,让我快速提出一个未经测试的次要建议:
如果通过更改OR mt2.meta_key = \'is_sponsored\'
到AND
相应地移动它,你可以用$wpdb
:
$sfp_post_ids = $wpdb->get_col(
"
SELECT wp_posts.ID
FROM wp_posts
INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
INNER JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id)
INNER JOIN wp_postmeta AS mt2 ON (wp_posts.ID = mt2.post_id)
WHERE 1=1
AND ( wp_term_relationships.term_taxonomy_id = $term_id )
AND wp_posts.post_type = \'sfpposts\'
AND (wp_posts.post_status = \'publish\')
AND ( (wp_postmeta.meta_key = \'pd_city\'
AND CAST(wp_postmeta.meta_value AS CHAR)
LIKE \'%$sfp_search_meta%\')
OR (mt1.meta_key = \'pd_country\'
AND CAST(mt1.meta_value AS CHAR)
LIKE \'%$sfp_search_meta%\') )
AND mt2.meta_key = \'is_sponsored\'
GROUP BY wp_posts.ID
ORDER BY CASE WHEN mt2.meta_value = 0 THEN 1 END, wp_posts.post_date DESC
"
);
此时,您还有两个选项:
或者迭代
$sfp_post_ids
具有简单
foreach
并使用
get_post()
在该循环中单独进行,或者,如果您希望
WP_Query
- 分页、模板标记等-提要
$sfp_post_ids
到
post__in
参数如解决方案1所示。