从 UNIFIED QUERY not FOR EACH TABLE 计算 MATCH() AGAINST() 分数

dac*_*nts 10 mysql full-text-search php

我正在尝试为整个 SELECT 语句部分打分

SELECT *,MATCH(`result`) AGAINST('keyword') as `score` FROM `table1` WHERE MATCH(`result`) AGAINST('keyword')
UNION
SELECT *,MATCH(`content`) AGAINST('keyword') as `score` FROM `table2` WHERE MATCH(`content`) AGAINST('keyword')
UNION
SELECT *,MATCH(`text`) AGAINST('keyword') as `score` FROM `table3` WHERE MATCH(`text`) AGAINST('keyword')
Run Code Online (Sandbox Code Playgroud)

在这种情况下,分数是按表计算的 + 它们不是按相关性排序的

但我试过这种方法,它有效但不值得生产

SELECT * FROM (
    SELECT *,MATCH(`result`) AGAINST('keyword') as `score` FROM `table1` WHERE MATCH(`result`) AGAINST('keyword')
    UNION
    SELECT *,MATCH(`content`) AGAINST('keyword') as `score` FROM `table2` WHERE MATCH(`content`) AGAINST('keyword')
    UNION
    SELECT *,MATCH(`text`) AGAINST('keyword') as `score` FROM `table3` WHERE MATCH(`text`) AGAINST('keyword')
) as `combined` ORDER BY `score` DESC
Run Code Online (Sandbox Code Playgroud)

不喜欢上面的代码,因为每个表都有分数,它们是连接和排序的。一个糟糕的做法。

于是,我就MATCH() AGAINST()data在顶级SELECT以及这一点。(没用)

SELECT *,MATCH(`data`) AGAINST('keyword') as `good_score` FROM (
        SELECT *,`result` as `data`,MATCH(`result`) AGAINST('keyword') as `score` FROM `table1` WHERE MATCH(`result`) AGAINST('keyword')
        UNION
        SELECT *,`content` as `data`,MATCH(`content`) AGAINST('keyword') as `score` FROM `table2` WHERE MATCH(`content`) AGAINST('keyword')
        UNION
        SELECT *,`text` as `data`,MATCH(`text`) AGAINST('keyword') as `score` FROM `table3` WHERE MATCH(`text`) AGAINST('keyword')
    ) as `combined` ORDER BY `good_score` DESC
Run Code Online (Sandbox Code Playgroud)

上面的语句对我来说是完美的,但它不起作用,因为data列是即时创建的,并且它不支持具有 FULLTEXT INDEX。

我的问题是如何继续让我的引擎工作。

  • 你能以某种方式使data一个FULLTEXT
  • 除了不支持分数的 IN BOOLEAN MODE 之外,还有什么方法可以使它工作
  • 是否有解决整个主题的方法可以使其发挥作用?创建临时表并不能解决这个问题,MATCH() AGAINST()的50%规则使得查询返回0结果,但是有很多
  • 也许有一些我想念的东西?
  • 创建 VIEW 也不起作用,MySQL 不支持 VIEW 上的 INDEX-es。
  • 也许使用 IN BOOLEAN 模式并手动创建评分是个好主意?

我已经为这个问题工作了两天多。所以我恳请寻求帮助。谢谢。

Rol*_*DBA 2

也许您可以从三(3)个表中记录以下内容

  • 表名
  • 表名中的列
  • 列上的 FULLTEXT 索引

这是代码:

DROP TABLE IF EXISTS combined_data;
CREATE TABLE combined_data
(
    source_table VARCHAR(64),
    source_id INT NOT NULL,
    data TEXT NOT NULL,
    FULLTEXT (data)
) ENGINE=MyISAM;
--
ALTER TABLE combined_data DISABLE KEYS;
--
INSERT INTO combined_data (source_table,source_id,data) VALUES
SELECT 'table1',id,`result` FROM table1 WHERE MATCH(`result`) AGAINST('keyword');
--
INSERT INTO combined_data (source_table,source_id,data) VALUES
SELECT 'table2',id,`content` FROM table1 WHERE MATCH(`content`) AGAINST('keyword');
--
INSERT INTO combined_data (source_table,source_id,data) VALUES
SELECT 'table3',id,`text` FROM table1 WHERE MATCH(`text`) AGAINST('keyword');
--
ALTER TABLE combined_data ENABLE KEYS;
Run Code Online (Sandbox Code Playgroud)

现在您可以对一个表运行单个查询

SELECT *,MATCH(`data`) AGAINST('keyword') as `good_score`
FROM combined_data
ORDER BY `good_score` DESC;
Run Code Online (Sandbox Code Playgroud)

试一试 !!!