поиск по релевантности в нескольких связанных таблицах

У меня есть таблица с именем cards, которая имеет связанные таблицы brigades и identifiers. У одной карты может быть несколько бригад и идентификаторов. Я хочу выполнить единый поиск, такой как 'purple king', где «фиолетовый» — это бригада, а «король» — идентификатор, и найти карты с этими бригадами и идентификаторами. Этот ответ на аналогичный вопрос, https://stackoverflow.com/a/9951200/633513, показал, как вы можете поиск по нескольким таблицам. Я хотел бы сделать то же самое, за исключением того, что мне нужны связанные совпадения. Это возможно?

Структуры таблиц:

Cards: id as INT, title as VARCHAR(50)
Brigades: id as INT, brigade as VARCHAR(50)
Identifier: id as INT, identifier as VARCHAR(50)

Присоединяйтесь к столам:

CardBrigades: id as INT, card_id as INT, brigade_id as INT
CardIdentifiers: id as INT, card_id as INT, identifier_id as INT

Примеры идентификаторов:

Angel
Animal
Archer
Army
Assyrian
Babylonian
Based on Prophecy
Beast
Bows, Arrows, Spears, Javelins and Darts
Canaanite
'Capture' in Special Ability
'Censer' in Title
Chief Priest
Child of Leah
Commander
Connected to David
Connected to Demons
'Covenant' in Title
'David' in Title
'David' in Verse
Deacon
Prince

Образцы бригад:

None
Black
Brown
Crimson
Gold (Evil)
Gray
Orange
Pale Green
Multi (Evil)
Blue
Gold (Good)
Green
Purple
Red
Silver
Teal
White
Multi (Good)
Multi

person LordZardeck    schedule 31.03.2012    source источник
comment
Эта структура таблицы на самом деле не показывает отношения. Есть ли в карточках столбцы для значений Brigades.id и Identifier.id? Или Bridgades значения Cards.id? Что-то кажется не так.   -  person Ilion    schedule 31.03.2012
comment
Можете ли вы предоставить некоторые образцы данных? Включают ли поля VARCHAR только «фиолетовый» и т. д., или они также могут включать «фиолетовое сердце», которое вы также хотите сопоставить.   -  person liquorvicar    schedule 31.03.2012
comment
@Ilion, извини, я забыл о таблицах соединений. Я обновил вопрос с ними.   -  person LordZardeck    schedule 31.03.2012
comment
@liquorvicar Я обновил вопрос с примерами данных   -  person LordZardeck    schedule 31.03.2012


Ответы (2)


Основываясь на ответе в ссылке, которую вы разместили, вы можете сделать что-то вроде этого

SELECT id,SUM(relevance) as total_relevance FROM (
SELECT 
    id, 
    (MATCH(title) AGAINST ('search string')) AS relevance
    FROM Cards
UNION
SELECT 
    Cards.id,
    (MATCH(brigade) AGAINST ('search string')) AS relevance
    FROM Brigades 
    INNER JOIN CardBrigades ON Brigades.id=brigade_id
    INNER JOIN Cards ON card_id=Cards.id 
UNION
SELECT 
    Cards.id,
    (MATCH(identifier) AGAINST ('search string')) AS relevance
    FROM Identifier 
    INNER JOIN CardIdentifier ON Identifier.id=identifier_id
    INNER JOIN Cards on card_id=Cards.id 
) AS combined_search 
GROUP BY id
HAVING total_relevance > 0

Я не уверен, насколько хорошо это будет работать. Возможно, вам лучше рассмотреть другое решение, такое как Solr, Lucene или даже механизм хранения NoSQL.

person liquorvicar    schedule 31.03.2012
comment
Я смог получить это, но как мне найти тот, который связан? Например, приведенный выше поиск с использованием этого запроса даст мне королей, которые не фиолетовые. - person LordZardeck; 31.03.2012
comment
@LordZardeck Я не уверен, что вы можете идеально достичь того, чего хотите, в MySQL. Возможно, вам лучше использовать специальную поисковую систему для строк. - person liquorvicar; 31.03.2012
comment
как насчет того, чтобы узнать, сколько обращений по одному идентификатору карты? тогда вы могли бы заказать, сколько хитов, чтобы найти mos релевантную право? - person LordZardeck; 01.04.2012
comment
@LordZardeck Я думаю, вы могли бы переключить предложение HAVING на подзапросы, а затем выполнить подсчет. Это может сработать. - person liquorvicar; 01.04.2012

Если вам просто нужны связанные (релевантные?) результаты, вы можете использовать ПОЛНОТЕКСТНЫЙ поиск в БУЛЕВОМ РЕЖИМЕ следующим образом:

select 
    identifier, brigade, P.id as identifier_id, B.id as brigade_id, 
    match(identifier)  against ('purple prince') +
    match(brigade)     against ('purple prince')   as score
from Identifier P, Brigade B
where 
    match(identifier)  against ('purple prince' IN BOOLEAN MODE) and 
    match(brigade)     against ('purple prince' IN BOOLEAN MODE)
order by -score
;

(Для упрощения я просто показываю часть запроса FULLTEXT search и опускаю соединение с таблицей Card*)

person quanalyst    schedule 12.10.2013