繁体   English   中英

具有中间首字母的 meta_query 搜索名称 - PHP、WordPress

[英]meta_query search names when they have middle initials - PHP, WordPress

我必须建立一个搜索表单,在其中按全名(名字+中间名首字母+姓氏)搜索公司成员。 所有的名字都采用这种形式: John B. Doe

以下代码正在处理这些情况: John, John B., Doe, B., John B. Doe ,但查询搜索不工作的是: John Doe

 if (isset($_POST['search']) && $_POST['search'] != -1) {
    $args['meta_query']['name_search']['key'] = "_full_name";
    $args['meta_query']['name_search']['compare'] = "LIKE";
    $args['meta_query']['name_search']['value'] = $_POST['search'];
  }

我应该如何改进查询以便同时使用:姓名和姓氏 (John Doe) 以及姓名、姓氏和中间名首字母 (John B. Doe)?

首先,如果只有 WordPress 没有转义value中的%字符(即搜索关键字),你可以简单地将搜索关键字中的空格替换为% ,因此你会得到一个像meta_value LIKE '%John%Doe%'匹配John B. Doe

因此,因为搜索关键字中的%被转义(这是一件好事,顺便说一句),所以您可以改用REGEXP (正则表达式搜索),然后用.*替换空格,这相当于LIKE中的%条款。

工作示例

在您的代码中替换它:

$args['meta_query']['name_search']['compare'] = "LIKE";
$args['meta_query']['name_search']['value'] = $_POST['search'];

有了这个:

// Build the regular expression pattern.
$list = preg_split( '/ +/', trim( $_POST['search'] ) );
$regex = implode( '.*', array_map( 'preg_quote', $list ) );

// Then set 'compare' to REGEXP and 'value' to the above pattern.
$args['meta_query']['name_search']['compare'] = 'REGEXP';
$args['meta_query']['name_search']['value'] = $regex;

在 WordPress 5.7.2 中进行了尝试和测试,但请注意MySQL 参考手册中的“非多字节安全”警告。

替代解决方案(相当于上述一种)

如果您想使用LIKE而不是REGEXP ,但又不想对同一个键进行潜在的大量元查询,那么您可以:

使用三个搜索字段,即名字、姓氏和中间名首字母,以及三个元子句,每个搜索字段一个,但都将key设置为_full_name 例如

/*
 * Assuming your form contains these:
    <input name="first_name">
    <input name="last_name">
    <input name="middle_initial">
 */

$name_search = array(
    'relation' => 'AND',
);

// * okay, this still uses 3 clauses, but it always would be just 3 clauses
foreach ( array( 'first_name', 'last_name', 'middle_initial' ) as $name ) {
    if ( ! empty( $_POST[ $name ] ) ) {
        $name_search[ $name ] = array(
            'key'     => '_full_name',
            'value'   => sanitize_text_field( $_POST[ $name ] ),
            'compare' => 'LIKE',
        );
    }
}

$args['meta_query']['name_search'] = $name_search;

我可以建议以下解决方案:

$search = $_POST['search'];
$words  = explode( $search, ' ' );
$words  = array_filter(
    $words,
    function ( $word ) {
        return ! empty( trim( $word ) );
    }
);

foreach ( $words as $index => $word ) {
    $query_name          = "name_search_$index";
    $args['meta_query'][ $query_name ] = [
        'key'     => '_full_name',
        'value'   => $word,
        'compare' => 'LIKE',
    ];
}

代码说明:

  1. 我将搜索短语拆分为单词。 单词是空格之间的任何符号序列
  2. 我删除空格。 如果您的搜索字符串是
    约翰·多伊
    或者
    约翰·多伊
    或者
    约翰·多伊
    搜索结果应该是一样的。
  3. 我构建了多个查询。 每个查询对应一个单词。 如果您搜索 John Doe,则查询由 2 个查询构建。 查询与字数一样重要。

此解决方案的问题:

  1. 太多的单词就是太多的查询。 太多包含 LIKE 的查询太慢。
  2. 您将获得相同的搜索结果
    约翰·多伊
    美国能源部约翰
    . 单词的顺序对结果没有影响。

我建议仅将此解决方案用作临时解决方案。 好的解决方案 - 使用全文搜索插件或自己编写全文搜索解决方案。 More details about FullText search you could find on MySQL official page: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM