【问题标题】:MySQL Full Text Search in subquery returning no results子查询中的 MySQL 全文搜索没有返回结果
【发布时间】:2017-02-12 19:14:22
【问题描述】:

我正在为我的 typeahead 输入设置 API,它按姓名返回用户,并选择 MySQL 全文搜索而不是连接名字、中间名和姓氏,这样用户在输入姓名时可以有更大的灵活性,而不必担心正确的顺序。

例如'Carolina Del'、'Delgado Caro' 等都会将用户与 first_name="Carolina"、middle_name=""、last_name="Delgado" 的 user_names 表中的相应值进行匹配。

由于某种原因,在用户/用户名约束之后使用全文搜索时,我得到的结果为零,但在使用 LIKE 时,我确实得到了正确的结果。

以下给出 0 个结果

SELECT count(*) FROM `users`
    WHERE (select count(*) from `user_names`
        WHERE `user_names`.`user_id` = `users`.`id`
        AND MATCH(first_name, middle_name, last_name)
        AGAINST ('+carolina' IN BOOLEAN MODE)
    ) >= 1;

当与 LIKE 一起使用时,我们得到 47 个结果

SELECT count(*) FROM `users`
    WHERE (select count(*) FROM `user_names`
        WHERE `user_names`.`user_id` = `users`.`id`
        AND `first_name` LIKE "%carolina%")
    >= 1;

为了显示全文索引工作正常,这里是一个直接在用户名表上的查询,它也给出了 47 个结果

SELECT count(*) FROM `user_names`
    WHERE MATCH(first_name, middle_name, last_name)
     AGAINST ('+carolina' IN BOOLEAN MODE);

对于它的价值,我在 Laravel 查询构建器范围内使用它,但由于它产生的 SQL(以上)不起作用,我需要首先了解原因。

public function scopeForContactName($query, $name)
{
return $query->whereHas('contact.name', function ($query) use ($name) {
        $query->where(function ($q) use ($name) {
            $q->whereRaw("MATCH(first_name, middle_name, last_name) AGAINST (? IN BOOLEAN MODE)", [$name]);
        });
    });
}

【问题讨论】:

    标签: mysql full-text-search


    【解决方案1】:

    这是通过将索引存储设置为升序来解决的。

    我之前是这样创建索引的:

    CREATE FULLTEXT INDEX full_text_index ON `user_names` (`first_name`, `middle_name`, `last_name`)
    

    以下调整后的 SQL 修复了该问题:

    CREATE FULLTEXT INDEX full_text_index ON `user_names` (`first_name` ASC, `middle_name` ASC, `last_name` ASC)
    

    这似乎与 MySQL 的文档相违背:

    index_col_name 规范可以以 ASC 或 DESC 结尾。这些关键字被允许用于指定升序或降序索引值存储的未来扩展。目前,它们被解析但被忽略;索引值始终按升序存储。 MySQL 5.7 Docs

    但无论如何,对我有用!

    【讨论】:

    • 由于FULLTEXT 没有ASCDESC 的概念,我很惊讶这有什么不同。
    【解决方案2】:

    第一个查询没有意义。子查询返回 1 行——一个计数;外部查询应该正好看到一行要计数。

    你从这个公式中得到了什么?

    SELECT count(*)
        FROM `users` AS u
        JOIN `user_names` AS un  ON un.`user_id` = u.`id`
        WHERE  MATCH(un.first_name, un.middle_name, un.last_name)
               AGAINST ('+carolina' IN BOOLEAN MODE);
    

    (对我而言)将名称放在users 表中更有意义,而不是单独的表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多