【问题标题】:Wordpress meta_query an array of values when metadata to compare is serialized array?当要比较的元数据是序列化数组时,Wordpress meta_query 一个值数组?
【发布时间】:2017-10-03 00:57:45
【问题描述】:

我正在尝试使用一组值运行 meta_query,并让它搜索是否所有都存在于存储在序列化数组中的元值中。这可能吗?

我的查询参数如下(注意这是嵌套在一个类中):

$args = array(
    'post_type' => $this->posttype,
    'posts_per_page' => '9',
    'paged' => $paged,
    'orderby' => 'meta_value_num',
    'order' => 'DESC',
    'meta_key' => 'lumens',
    'meta_query' => array(
        array(
            'key' => 'mount',
            'value' => array('pendant' , 'wall'),
            'compare' => 'IN'
        )

    )
);

存储的元数据的一个例子,是在一个类似下面的序列化数组中:

a:4:{i:0;s:7:"pendant";i:1;s:15:"surface-ceiling";i:2;s:4:"wall";i:3;s:14:"aircraft-cable";}

无论我尝试什么,我的查询都不会返回适当的结果。我现在意识到我可能应该将每个值存储在不同的元键中,而不是存储在数组中,但是,现在已经有很多条目可以更改元数据。

更新:

这是我的解决方法,类似于@Leander 方法;由于数据库中已经存在大量条目,我不想更改序列化输入,还有一件事我忘了提及,我正在使用CMB2 Developer Toolkit,它将复选框字段本地存储为序列化数据。

// This is pulled from a user input
$meta_queries = array('pendent' , 'wall');

// Metaqueries are passed through loop to create single entries with the like comparison operator
foreach($meta_queries as $key => $value){

    $meta_query = array(
        'key' => '_tf_' . $key,

        // Serialize the comparison value to be more exact
        'value' => serialize(strval($value)),
        'compare' => 'LIKE',
    );

}

// Generate $args array
$args = array(

    'post_type' => $this->posttype,
    'posts_per_page' => '9',
    'paged' => $paged,
    'orderby' => 'meta_value_num',
    'order' => 'DESC',
    'meta_key' => 'lumens',
    'meta_query' => $meta_queries

);

在填充数据时,我没有注意到很多性能问题。我想如果要处理大量数据,这种方法将不得不重新设计。

【问题讨论】:

    标签: php wordpress metadata cmb2


    【解决方案1】:

    刚刚遇到同样的问题...!

    我有一些标签存储在一个数组/自定义字段中,并且正在使用搜索表单来查询我的帖子,其中应该允许用户搜索多个标签,所以基本上我需要将一个数组与另一个数组进行比较。

    我现在意识到我可能应该将每个值存储在不同的元键中,而不是存储在数组中,但是,现在已经有很多条目需要更改元数据。

    我想这会产生相当大的开销,不建议这样做......

    方法/解决方法

    我将用户输入作为字符串处理,从字符串中创建一个数组以检查其大小,并根据大小创建单个 LIKE 比较,它可以很好地处理我的数组数据。

    $tags_string = get_query_var( 'p_tags' ); // form submitted data
    $tags_array = explode( ',', $tags_string ); // create array
    
    if ( count( $tags_array ) > 1 ) { // check if more then one tag
    $meta_query['p_tags']['relation'] = 'AND';
    
    foreach($tags_array as $tag) { // create a LIKE-comparison for every single tag
        $meta_query['p_tags'][] = array( 'key' => 'YOUR_KEY', 'value' => $tag, 'compare' => 'LIKE' );
    }
    } else { // if only one tag then proceed with simple query
        $meta_query['p_tags'] = array( 'key' => 'YOUR_KEY', 'value' => $tags_string, 'compare' => 'LIKE' );
    }
    

    Args 输出(演示)

    [meta_query] => Array
            (
                [p_tags] => Array
                    (
                        [relation] => AND
                        [0] => Array
                            (
                                [key] => basic_tags
                                [value] => adobe
                                [compare] => LIKE
                            )
    
                        [1] => Array
                            (
                                [key] => basic_tags
                                [value] => stone
                                [compare] => LIKE
                            )
    
                    )
    
            )
    

    注意:根据您的数组大小、要查询的帖子数量等,此解决方案可能不是性能最高的解决方案。

    另一种方法可能是 WordPress 查询的 FIND_IN_SET 扩展,see this gist

    感谢有关性能或改进代码质量的任何意见。

    【讨论】:

    • 我有点晚了,但是,我在上面发布了我的决心。感谢您的意见。
    【解决方案2】:

    现在要更改元数据的条目太多了

    然后运行脚本(PHP 脚本或直接 MySQL)并创建正确的 meta_key => meta_value 对,然后删除您的序列化列。序列化数据只有在要这样检索时才应存储在数据库中。如果您很懒惰并且仍然只想拥有一列,请将数据存储为 JSON,然后以 JSON 形式查询它们(现代版本的 MySQL 允许从 JSON 类型的列中查询 json 数据)。祝你好运。

    但是,如果您坚持并保持数据序列化,我向您保证,您或维护您的项目的任何人都会为您需要实现的每个相关小功能而努力。

    【讨论】:

      【解决方案3】:

      由于元数据在数据库列中被序列化,并且在技术上表示为字符串,因此您可以进行 REGEXP 比较。

      你的例子引用了。

      元值(数据库)

      a:4:{i:0;s:7:"pendant";i:1;s:15:"surface-ceiling";i:2;s:4:"wall";i:3;s:14:"aircraft-cable";}
      

      查询

      $args = array(
          'post_type' => $this->posttype,
          'posts_per_page' => '9',
          'paged' => $paged,
          'orderby' => 'meta_value_num',
          'order' => 'DESC',
          'meta_key' => 'lumens',
          'meta_query' => array(
              array(
                  'key' => 'mount',
                  'value' => '"(pendant|wall)"',
                  'compare' => 'REGEXP'
              )
      
          )
      );
      

      或者,如果您有一个值数组,您可以执行以下操作。

      array(
           'key' => 'mount',
           'value' => '"('. implode('|', array('pendant' , 'wall')) .')"',
           'compare' => 'REGEXP'
      )
      

      注意

      如果您的“值”值包含需要为有效的正则表达式转义的特殊字符,请使用 preg_quote 函数。否则,此解决方案应该 100% 有效。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-27
        • 2021-04-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-01
        • 2019-08-12
        • 1970-01-01
        相关资源
        最近更新 更多