views:

18

answers:

1

I'm trying to add a full text search to a system. The query I want to write needs to involve multiple lookups followed by the search (if that's even possible).

I've got a table of teachers and a table of subjects.

teacherProfile
teacherId [int] - primary key
subjectOneId [int]
subjectTwoId [int]
subjectThreeId [int]
teacherBiography [text]

subjects
subjectId [int]
subjectName [text]

So ultimately I want a resultset along the lines of..

teacherId [int]
teacherBiography [text]
( subjectOneName [text] )
( subjectTwoName [text] )
( subjectThreeName [text] )

So these last three fields in brackets are non existant but I do want to perform a text search upon them, do I need to setup a foriegn key constraint (which I'd rather not to do in case of further impacts on the existing system) or is there something more eloquent I can do?

+2  A: 

MySQL cannot index views so what you want is impossible in MySQL.

You can use an external fulltext indexing engine like Sphinx and load data there using a query with JOINS

Alternatively, you can create a denormalized table:

CREATE TABLE ftsearch
        (
        teacherId INT PRIMARY KEY,
        teacherBiography TEXT,
        subject1 TEXT,
        subject2 TEXT,
        subject3 TEXT,
        )
ENGINE=MyISAM

and fill it with this query:

INSERT
INTO    ftsearch
SELECT  teacherId, teacherBiography,
        s1.name, s2.name, s3.name
FROM    teacherProfile
LEFT JOIN
        subject s1
ON      s1.id = subjectOneId 
LEFT JOIN
        subject s2
ON      s2.id = subjectTwoId 
LEFT JOIN
        subject s3
ON      s3.id = subjectThreeId 

on a timely basis.

Actually, if all your tables are MyISAM, you can apply fulltext search queries (in boolean mode) to a join, without having to create a fulltext index.

Say, if you are searching for '+Jones +math +physics', where Jones is a teacher's surname and math and physics are subjects, you can do this query:

SELECT  teacherId, teacherBiography,
        s1.name, s2.name, s3.name
FROM    teacherProfile
LEFT JOIN
        subject s1
ON      s1.id = subjectOneId 
LEFT JOIN
        subject s2
ON      s2.id = subjectTwoId 
LEFT JOIN
        subject s3
ON      s3.id = subjectThreeId 
WHERE   MATCH(teacherBiography) AGAINST ('+Jones' IN BOOLEAN MODE)
        AND MATCH(t.teacherBiography, s1.name, s2.name, s3.name) AGAINST ('+Jones +math +physics' IN BOOLEAN MODE)

The MATCH(teacherBiography) AGAINST ('+Jones') will use a FULLTEXT index on teacher, if any; the second MATCH will fine-filter the results.

Queries involving the OR conditions or relevance sorting are more complex, however.

Quassnoi
Brilliant, thanks Quassnoi for your excellent response.
Julian Young
Actually, If I skipped the full text search how would I do the lookup without the existance of the last three fields? I.e. get the results for the view AND perform full text search on the bio?
Julian Young
@Julian: lookup of what?
Quassnoi
Sorry - getting the textual subject lookup results for the view AND performing a full text search on the bio?
Julian Young
@Julian: please provide an example of your query (I mean a phrase you will be putting into a search column)
Quassnoi
Hmm won't let me put the query in here, I'll post another question...
Julian Young
http://stackoverflow.com/questions/3865783/mysql-compare-on-join-problem
Julian Young