0

Fulltext searchin with InnoDB in MySQL only includes certain characters referred to in the docs as "word characters" and mentioned here:

For the built-in full-text parser, you can change the set of characters that are considered word characters in several ways, as described in the following...

My question is, for a given character set, how can I determine which characters are considered "word" characters? My table is utf_general_ci. I did a bit of trial and error and found for instance, that "¬" is not treated as a word character but "Ω" is. I'm looking for either a clearly defined reference or a tool of some support so that I can find this out without doing trial and error.

4
  • 1
    Note that Ω is a Greek "letter"; ¬ is a mathematical symbol.
    – Rick James
    Commented Sep 13, 2019 at 4:47
  • @RickJames - you're right but is a greek letter and through trial and error I've discovered that it's not treated as a word character, although Ω is. Commented Oct 4, 2019 at 13:32
  • Interesting. How about expanding your experiment to determine which Greek letters are "word" letters (in upper and lower case).
    – Rick James
    Commented Oct 4, 2019 at 18:27
  • I'm using these as a workaround for a fulltext search which I just posted about here. At the moment I only need a couple to act as substitutions so I didn't do anything very exhaustive. The ones I found that are treated as word chars are: Ω œ π ß µ. Commented Oct 4, 2019 at 18:31

2 Answers 2

1

The characters considered for forming a word, is explained in the Documentation:

The MySQL FULLTEXT implementation regards any sequence of true word characters (letters, digits, and underscores) as a word. That sequence may also contain apostrophes ('), but not more than one in a row. This means that aaa'bbb is regarded as one word, but aaa''bbb is regarded as two words. Apostrophes at the beginning or the end of a word are stripped by the FULLTEXT parser; 'aaa'bbb' would be parsed as aaa'bbb.

Regarding Delimiters:

The built-in FULLTEXT parser determines where words start and end by looking for certain delimiter characters; for example, (space), , (comma), and . (period).

Besides the above, there are Storage engine specific limits as well, on the minimum word size:

Any word that is too short is ignored. The default minimum length of words that are found by full-text searches is three characters for InnoDB search indexes, or four characters for MyISAM.

Now, regarding the list of defined "True Word Characters", MySQL has given flexibilities, to be able to add/remove additional characters, for word criteria. As stated in the Documentation:

Suppose that you want to treat the hyphen character ('-') as a word character. Use one of these methods:

  • Modify the MySQL source: In storage/innobase/handler/ha_innodb.cc (for InnoDB), or in storage/myisam/ftdefs.h (for MyISAM), see the true_word_char() and misc_word_char() macros. Add '-' to one of those macros and recompile MySQL.

  • Modify a character set file: This requires no recompilation. The true_word_char() macro uses a “character type” table to distinguish letters and numbers from other characters. . You can edit the contents of the array in one of the character set XML files to specify that '-' is a “letter.” Then use the given character set for your FULLTEXT indexes.

Now looking at the source code ha_innodb.cc here:

#define true_word_char(c, ch) ((c) & (_MY_U | _MY_L | _MY_NMR) || (ch) == '_')

For some simple character-sets like latin1, one can edit the <ctype><map> array in the respective .xml file: https://github.com/mysql/mysql-server/blob/5.7/sql/share/charsets/latin1.xml#L25

However, utf8 being a complex character-set, it is implemented in the ctype-utf8.c file . It contains the complete character set definitions. Now, array elements are bit values. Each element describes the attributes of a single character in the character set. Each attribute is associated with a bitmask, as defined in include/m_ctype.h file:

#define _MY_U   01  /* Upper case */
#define _MY_L   02  /* Lower case */
#define _MY_NMR 04  /* Numeral (digit) */

So, the characters having attributes associated with above bitmasks will be considered as true word character. Check out some explanation here --> https://dev.mysql.com/doc/refman/5.7/en/character-arrays.html

Finally, there is a list of stopwords (InnoDB has limited list, but MyISAM has quite a big list), which are ignored. Eg: about, are, com etc.

Words in the stopword list are ignored. A stopword is a word such as “the” or “some” that is so common that it is considered to have zero semantic value. There is a built-in stopword list, but it can be overridden by a user-defined list.

2
  • Isn't ¬ a letter? The definition is too vague - I need some way to know what constitutes a "letter" in a given charset otherwise I'm just guessing. Commented Sep 12, 2019 at 10:38
  • @billynoah Check the edited answer. Unfortunately, there isn't any proper documentation giving out all the characters considered in the uppercase, lowercase and numeric lists. So, only way left is to explore the source code files (as given in the answer above), to figure out for specific characters. Commented Sep 12, 2019 at 12:33
0

(Really a Comment, but need formatting, so writing this as an Answer.)

Be cautious of look-alikes:

β  GREEK SMALL LETTER BETA
ß  LATIN SMALL LETTER SHARP S  (German "ss")  (You had this)

μ  GREEK SMALL LETTER MU
µ  MICRO SIGN                    (You had this)

œ  LATIN SMALL LIGATURE OE     (in old writings; often written as "oe")

I would expect "LATIN" and "GREEK" letters to be letters in the Fulltext "word" sense. However, this does not fully match the pattern you discovered.

On the other hand, µsec for "microsecond" would probably be a FULLTEXT "word".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.