Search code examples
mysqlsearchfull-text-searchrelevance

relevance search across multiple related tables


I have a table called cards which has related tables brigades and identifiers. A single card can have multiple brigades and identifiers. I want to take a singe search such as 'purple king' where 'purple' is a brigade and 'king' is an identifier, and find cards with those brigades and identifiers. This answer to a similar question, https://stackoverflow.com/a/9951200/633513, showed how you can fulltext search across multiple tables. I'd like to do the same thing, except i just want related matches. Is this possible?

Table Structures:

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

Join Tables:

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

Sample Identifiers:

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

Sample Brigades:

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

Solution

  • Based on the answer in the link you posted you could do something like this

    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
    

    I'm not sure how well this would perform. You might be better off looking at another solution such as Solr, Lucene or even a NoSQL storage engine.