Are you looking for a guide on implementing the MySQL full text searching feature? Do you want to know how to accurately find documents in your database that match a user’s search query?
If you answered yes to any of these questions, this tutorial is for you! This guide will show you how to enable and configure the MySQL full-text searching feature to find contents in your database.
Read on to get started!
Table of Contents
This tutorial will be a hands-on demonstration. If you’d like to follow along, you must have the following requirements.
- You must have a MySQL server already installed and configured on a Linux computer. This tutorial uses a MySQL 8.0.28 on Ubuntu 20.04.
- You must have an empty database or create a new one if there is none. This database is where you’ll create the table and insert sample data for indexing. This tutorial will be using a database named
Creating the MySQL Full Text Searching Index
There are three methods to add a full-text search index to a table. Each method, while using different statements, achieves the same result.
Option 1: Using the CREATE TABLE Statement (New Table)
Typically, you would create a new table and already know which columns to add to the full-text index. Suppose you need to create a table containing article posts with columns such as:
id: The primary key that uniquely identifies each row in the table. The integer value in this column increments with each new row.
title: This column stores the article titles.
content: This column stores the content or body of the articles.
author: This column stores the author’s name.
In this case, you’ll want to include the
author into the MySQL full text searching index when you create the table. Follow the below steps to create the new table.
1. First, log in to your server using your preferred SSH client.
2. Now, connect to the MySQL server. This example logs in to MySQL using the default MySQL root user.
If you have a different MySQL user account, run the below command instead. Make sure to replace USERNAME with your MySQL user account.
mysql -u USERNAME -p
3. Now, create a new table named ata_tb in the ata_db database by running the following statement:
The PRIMARY KEY(id) specifies that the table’s primary key will be the id column.
The FULLTEXT ata_post_index (title,content,author) creates a full-text search index called ata_post_index. The full-text index includes the title, content, and author columns.
-- Select the ata_db database USE ata_db; -- Create the ata_tb table with indexing CREATE TABLE ata_tb ( id INT NOT NULL AUTO_INCREMENT, title TEXT NOT NULL, content TEXT NOT NULL, author TEXT NOT NULL, PRIMARY KEY (id), FULLTEXT ata_post_index (title, content, author) );
The below screenshot shows the result of the successful table creation.
Option 2: Using the ALTER TABLE Statement (Existing Table)
What if you previously created a table and did not include any full-text search indexing? Or perhaps there’s an existing table, and you want to add a full-text search index? You can do so by running the ALTER TABLE statement.
The full syntax below shows how to alter a table to add the full-text index.
ALTER TABLE table_name ADD FULLTEXT index_name (column_name1, column_name2,…)
To add the full-text index to the
ata_tb table, including the
author columns, execute the below statement. The resulting index name will be
-- ALTER the ata_tb table to create a full-text search index ALTER TABLE ata_tb ADD FULLTEXT ata_post_index (title, content, author);
After running the statement, you will likely get a warning, as you can see below.
Should you be worried about this warning? To answer that, show the warning message on the screen like so.
The warning below with the message
InnoDB rebuilding table to add column FTS_DOC_ID is normal when you first create the full-text index on a table. The storage engine is rebuilding the table with a new
FTS_DOC_ID column for indexing. This warning is informational.
Option 3: Using the CREATE INDEX Statement (Existing Table)
Another way to create a full-text index on an already existing table is with the CREATE INDEX statement. The full statement syntax is shown below.
CREATE FULLTEXT INDEX index_name ON table_name (column_name1, column_name2, ... );
Following that syntax, run the statement below to create a full-text index called
ata_post_index on the
ata_tb table. This full-text index will include the
-- Creating a full-text index on a table CREATE FULLTEXT INDEX ata_post_index ON ata_tb(title, content, author); -- Show the warning messages on the screen SHOW WARNINGS;
If you create the full-text index for the first time in this table, you will get the same warning message that says
InnoDB rebuilding table to add column FTS_DOC_ID, which is informational. This warning message does not require any action from you.
Inserting Sample Data into the Table
The new table is empty, and you must insert new rows of data for indexing. To insert new sample data into the table, run the below INSERT INTO statement. The below statement inserts three rows into the title, content, and author columns.
You don’t need to include the id column because MySQL inserts an autoincrementing integer value with new each row.
INSERT INTO ata_tb (title, content, author) VALUES ( 'Get Paid to Write', 'ATA Learning is always seeking instructors of all experience levels. Regardless if you''re a junior admin or system architect, you have something to share.', 'Adam' ), ( 'Automate your Java Builds', 'If you''re a developer, you''d typically prefer to automate the tedious manual build deployment process.', 'Sagar' ), ( 'Tapping Cloudflare Load Balancing to Route Server Traffic', 'Are you tired of applications and system outages whenever your site detects a spike in traffic?', 'Obare' );
As you can see below, the MySQL statement inserted three rows into the table.
You now have a demo table with sample data for indexing.
Using MySQL Full-Text Searching
Now that you have created a full-text index in the table, you can start running full-text searches on your data. MySQL provides the MATCH() AGAINST() function explicitly for doing full-text searches.
MATCH()takes a list of columns as an argument to search for the keyword you specify.
AGAINST()accepts the keyword to search and an optional search modifier.
By default, if you do not specify a modifier, the function uses the IN NATURAL LANGUAGE MODE modifier. This modifier interprets the keyword as a phrase in natural human language.
For example, run the below statement to search for the phrase ‘
are you’. The
Run the command below to see all the rows where the columns contain the phrase
Are you. The
\\G modifier tells MySQL to break the output into multiple lines instead of one long line with the semi-colon (
SELECT * FROM ata_tb WHERE MATCH (title, content, author) AGAINST ('Are you' IN NATURAL LANGUAGE MODE)\\G
As you can see in the output below, there is only one entry containing the phrase “
Are you”, but you get three results since the “
you're” string is also considered a match.
This behavior is helpful for typos when users search your site. When your users search for a term and don’t find what they are looking for, they will usually search for a similar term.
Returning Search Results by Order of Relevance
MySQL does not consider the relevance of each search result when returning them. You can make MySQL return results based on relevance by ranking them based on scores.
Rank, also known as relevance rank, is a score that MySQL gives to each row that matches the search condition. Scores are floating-point values, where 0 is the lowest relevance score.
Run the below command to see how MySQL ranks each row based on the query “
Adam You”. The condition
> 0 in the
WHERE clause will filter out all rows with a score of 0 (no relevance).
ORDER BY score DESC keyword sorts the results by relevance in descending order so that the most relevant results are on top.
SELECT id, MATCH (title, content, author) AGAINST ('Adam You') as score FROM ata_tb WHERE MATCH (title, content, author) AGAINST ('Adam You') > 0 ORDER BY score DESC;
You will get an output similar to the one below. You can see in the output that the row with id
1 has the highest score in the set, which makes it the most relevant to the search. The reason is that this row has both search terms
You in the
author columns, respectively.
The row with id
2 is in the second position because it contains only one of the search terms, “
You” in the
The row with id
3 is the least relevant because it only contains the term
This behavior can be helpful when your users search for multiple terms and you want to prioritize results that contain all of the search terms.
Full-Text Searching with Query Expansion
Now that you know how to order the results by relevance, you may be wondering if you can make the results even more relevant. Yes, you can — with query expansion. With query expansion, you can tell MySQL to automatically add related terms to the search phrase that the user entered.
This technique will give you more relevant results because it will find entries that contain the related terms even if they don’t contain the exact search phrase. For example, the search “database” could be expanded to “MySQL”, “Oracle”, “RDBMS”, etc.
The trade-off is that you may get more results than you want, even results not relevant to the original search. But, you can always include the
ORDER BY score DESC to rank the results by relevance and show only the most relevant ones.
The statement below shows the syntax that includes the
WITH QUERY EXPANSION modifier.
SELECT * FROM ata_tb WHERE MATCH (column_name1,column_name2,column_name3) AGAINST ('The_search_phrase' WITH QUERY EXPANSION);
In this example, you’ll create another table in the same database, insert data, and perform full-text searches with query expansion.
1. Create a new table named articles that includes the title and id columns in the full-text search index.
CREATE TABLE articles ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, title VARCHAR(200), body TEXT, FULLTEXT (title, body) );
2. Now, insert some data into the articles table.
INSERT INTO articles (title,body) VALUES ('MySQL Tutorial','DBMS stands for DataBase ...'), ('How To Use MySQL Well','After you went through a ...'), ('Optimizing MySQL','In this tutorial, we show ...'), ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), ('MySQL vs. YourSQL','In the following database comparison ...'), ('MySQL Security','When configured properly, MySQL ...');
3. Now, Run the below command to search for the term “database” in the title and body columns.
SELECT * FROM articles WHERE MATCH (title, body) AGAINST ('database');
As you can see below, the search two results; MySQL Tutorial and MySQL vs. YourSQL.
4. To further improve the relevance of the results, rerun the command above with the WITH QUERY EXPANSION modifier.
SELECT * FROM articles WHERE MATCH (title, body) AGAINST ('database' WITH QUERY EXPANSION);
This time, you have six results instead of the previous two. Why? MySQL conducts the search using two different search phrases. The first phrase only contains “database”. The second phrase is “database,” plus the most relevant documents from the first search.
In this case, one of these documents contains the word “database” and “MySQL”. MySQL uses this second phrase to retrieve more documents that contain the word “MySQL” that might be relevant to the search.
This behavior is useful when users make typographical errors or use different terms to mean the same thing.
In this guide, you have learned how to use the MySQL full-text searching function to find accurate results. You have also learned how to use the
WITH QUERY EXPANSION modifier to retrieve more relevant results even if they don’t contain the exact search phrase.