Reputation: 21
I have a MySQL table structured like this:
$sql = "CREATE TABLE test(
id INT NOT NULL,
title VARCHAR(512) NOT NULL COLLATE utf8_general_ci,
body TEXT NOT NULL COLLATE utf8_general_ci,
dateStored VARCHAR(32) NOT NULL COLLATE utf8_general_ci,
fileName VARCHAR(128) NOT NULL COLLATE utf8_general_ci,
FOREIGN KEY(id) REFERENCES `database`.`parent`(id)
);";
My storage engine is MYISAM.
Now, when I want to search in body
field with the MATCH
- AGAINST
, there is no result…
This is my try:
$sql2 = "SELECT * FROM database.test
WHERE MATCH(body) AGAINST('?')";
$prepare = $pdo->prepare($sql2);
$prepare->execute( array( $pattern ) );
$fetch = $prepare->fetchAll();
It seems very basic but still my code do not work. Would you tell me what is wrong with my code?
Is this because of I have a field with references to another table?
Upvotes: 2
Views: 2078
Reputation: 14522
You just need to add a FULLTEXT INDEX
altering the table like Crackertastic described or define it directly in the CREATE TABLE
statement.
Here is a working example:
-- DROP TABLE child;
-- DROP TABLE parent;
CREATE TABLE parent (
id INT NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB; -- or MyISAM
CREATE TABLE child(
id INT NOT NULL,
title VARCHAR(512) NOT NULL COLLATE utf8_general_ci,
body TEXT NOT NULL COLLATE utf8_general_ci,
date_stored VARCHAR(32) NOT NULL COLLATE utf8_general_ci,
file_name VARCHAR(128) NOT NULL COLLATE utf8_general_ci,
parent_id INT NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (parent_id) REFERENCES parent(id),
FULLTEXT (body)
) ENGINE=InnoDB; -- or MyISAM
INSERT INTO child (id, title, body, date_stored, file_name, parent_id) VALUES('1','test title 1','test body 1','22.05.2014','file1.txt',5);
INSERT INTO child (id, title, body, date_stored, file_name, parent_id) VALUES('2','asd','qwer','31.07.2019','yxcv.txt',6);
INSERT INTO child (id, title, body, date_stored, file_name, parent_id) VALUES('3','gfdsa','trewq','21.04.2015','hjkl.txt',7);
SELECT
*
FROM
child
WHERE
MATCH(body) AGAINST('qwer')
;
The SELECT
request returns the entry with the id = 2
.
In MySQL vesions older than 5.6 was not possible to define a FULLTEXT INDEX
on an InnoDB
table.
From the MySQL 5.5 docu:
Full-text indexes can be used only with
MyISAM
tables. (In MySQL 5.6 and up, they can also be used withInnoDB
tables.)
So, one had to decide between using of FOREIGN KEY
and FULLTEXT INDEX
and choose the storage engine -- InnoDB
or MyISAM
. Since InnoDB
supported FOREIGN KEY
constraints, but didn't support FULLTEXT
indexes.
An attempt to create a FULLTEXT INDEX
on an InnoDB
table
-- DROP TABLE child;
-- DROP TABLE parent;
CREATE TABLE parent (
id INT NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;
CREATE TABLE child(
id INT NOT NULL,
title VARCHAR(512) NOT NULL COLLATE utf8_general_ci,
body TEXT NOT NULL COLLATE utf8_general_ci,
date_stored VARCHAR(32) NOT NULL COLLATE utf8_general_ci,
file_name VARCHAR(128) NOT NULL COLLATE utf8_general_ci,
parent_id INT NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (parent_id) REFERENCES parent(id)
) ENGINE=InnoDB;
ALTER TABLE `child` ADD FULLTEXT (`body`);
failed with an error:
Query: ALTER TABLE `child` ADD FULLTEXT (`body`)
Error Code: 1214
The used table type doesn't support FULLTEXT indexes
So, you had to use MyISAM
for FULLTEXT INDEX
. Then you just need to add a FULLTEXT INDEX
altering the table like Crackertastic described or define it directly in the CREATE TABLE
statement.
Here is a working example:
-- DROP TABLE child;
-- DROP TABLE parent;
CREATE TABLE parent (
id INT NOT NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM;
CREATE TABLE child(
id INT NOT NULL,
title VARCHAR(512) NOT NULL COLLATE utf8_general_ci,
body TEXT NOT NULL COLLATE utf8_general_ci,
date_stored VARCHAR(32) NOT NULL COLLATE utf8_general_ci,
file_name VARCHAR(128) NOT NULL COLLATE utf8_general_ci,
parent_id INT NOT NULL,
PRIMARY KEY (id),
FULLTEXT (body)
) ENGINE=MyISAM;
INSERT INTO child (id, title, body, date_stored, file_name, parent_id) VALUES('1','test title 1','test body 1','22.05.2014','file1.txt',5);
INSERT INTO child (id, title, body, date_stored, file_name, parent_id) VALUES('2','asd','qwer','31.07.2019','yxcv.txt',6);
INSERT INTO child (id, title, body, date_stored, file_name, parent_id) VALUES('3','gfdsa','trewq','21.04.2015','hjkl.txt',7);
SELECT
*
FROM
child
WHERE
MATCH(body) AGAINST('qwer')
;
The SELECT
request returns the entry with the id = 2
.
Upvotes: 1
Reputation: 167
Try IN BOOLEAN MODE. This will not ignore any rows.
http://dev.mysql.com/doc/refman/5.6/en/fulltext-boolean.html
Upvotes: 1
Reputation: 4913
I think you are missing the FULLTEXT
index on your field. You need to have a FULLTEXT index on a column to do MATCH AGAINST
searches.
Either declare the FULLTEXT
index with the table or alter your current table to include the index.
ALTER TABLE `test` ADD FULLTEXT (`body`)
Also, as some others have said, there is a cut off to the word length and there is also the 50% threshold that will prevent results from showing.
Upvotes: 3
Reputation: 559
Add more data. By default MySQL will ignore any word that is in 50% or more of the rows in the table as it considers it would be a 'noise' word.
With very few rows in a table, it is common to hit this 50% limit often (ie. if you have two rows, every word is in at least 50% of the rows!).
Upvotes: 5