特定のケースで結果が重複するという事実を除いて、かなりうまく機能する全文MySQLクエリを取得しました。建物、スイート、資産など、検索しようとしているいくつかのタイプのデータがあり、それぞれが独自のテーブルにあります。各タイプのデータには、ユーザー定義のカスタム フィールドもあり、そのデータは別のテーブルに保存されます。これが私の構造です。
CREATE TABLE `buildings` (
`bid` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(250) COLLATE utf8_unicode_ci NOT NULL,
`status` enum('active','inactive') COLLATE utf8_unicode_ci NOT NULL,
`source` enum('feed','manual') COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`bid`),
FULLTEXT KEY `textsearch` (`name`)
)
CREATE TABLE `customfields` (
`cfid` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(250) COLLATE utf8_unicode_ci NOT NULL,
`datatype` enum('integer','date','smtext','lgtext','numeric','enum','linked') COLLATE utf8_unicode_ci NOT NULL,
`options` longtext COLLATE utf8_unicode_ci,
`did` int(11) NOT NULL COMMENT 'Datasheet ID',
PRIMARY KEY (`cfid`),
KEY `did` (`did`)
)
CREATE TABLE `customfield_data` (
`cfdid` int(11) NOT NULL AUTO_INCREMENT,
`data_int` int(11) DEFAULT NULL,
`data_date` datetime DEFAULT NULL,
`data_smtext` varchar(1000) COLLATE utf8_unicode_ci DEFAULT NULL,
`data_lgtext` longtext COLLATE utf8_unicode_ci,
`data_numeric` decimal(20,2) DEFAULT NULL,
`linkid` int(11) DEFAULT NULL COMMENT 'ID value of specific item',
`cfid` int(11) NOT NULL COMMENT 'Custom field ID',
PRIMARY KEY (`cfdid`),
KEY `data_smtext` (`data_smtext`(333)),
KEY `linkid` (`linkid`),
KEY `cfid` (`cfid`),
FULLTEXT KEY `textsearch` (`data_smtext`,`data_lgtext`)
)
そのため、実際のデータを customfield_data に格納するカスタム フィールドを建物に設定することができます。customfield は、did (データセット ID) によって建物固有のフィールドとして識別されます。cfid フィールドは customfield_data を customfield にリンクし、データは linkid フィールドを使用して特定の建物にリンクされます。
それを念頭に置いて、これが私の全文クエリです。
SELECT * FROM (
SELECT (data_smtext + data_lgtext) AS data, linkid AS idvalue, did, MATCH(data_smtext, data_lgtext) AGAINST (?) AS relevance
FROM customfield_data
JOIN customfields ON customfield_data.cfid = customfields.cfid
WHERE MATCH (data_smtext, data_lgtext) AGAINST (? IN BOOLEAN MODE)
UNION
SELECT name AS data, bid AS idvalue, 2 AS did, 3 * (MATCH(name) AGAINST (?)) AS relevance
FROM buildings
WHERE status = ? AND MATCH (name) AGAINST (? IN BOOLEAN MODE)
UNION
SELECT name AS data, bid AS idvalue, 2 AS did, 100 AS relevance
FROM buildings
WHERE bid LIKE ? AND status = ?
UNION
)
AS searchresults
WHERE relevance > 0
ORDER BY relevance DESC
先に述べたように、これはすべて問題なく機能します。私が直面している問題は、たとえば、建物の名前が123 North Ave Tower で、その住所(カスタムフィールド) が 123 North Ave である場合、レコードが重複することです。1 つは名前用で、もう 1 つは「123 North Ave」を検索した場合の住所。
どちらも同じ did (データセット ID) と linkid (この場合は building ID) を指しているので、結果の配列を PHP で循環させ、一致を探し、重複を捨てることで問題を解決できることがわかっています。 . しかし、そうするとパフォーマンスが低下し、関連性スコアリングの有効性も低下します。理想的には、より正確なスコアを得るために、クエリで住所一致の関連性を名前/ID 一致の関連性に追加できるようにしたいと考えています。現在、名前の一致を 3 倍にし、カスタムフィールドの一致を 1 倍にして、より正確な一致をより重く重み付けしていますが、2 つを追加するのが最良のオプションです。
私を正しい方向に向けることができる人に感謝します!