0

特定のケースで結果が重複するという事実を除いて、かなりうまく機能する全文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 つを追加するのが最良のオプションです。

私を正しい方向に向けることができる人に感謝します!

4

2 に答える 2

0

この特定の問題に対する解決策はありませんが、Sphinx をインストールして構成し、それで面倒な作業を行うことで解決しました。

于 2013-08-14T18:06:39.717 に答える