这是我的查询
SELECT * FROM myTable WHERE MATCH (name) AGAINST ("Apple M1" IN NATURAL LANGUAGE MODE)
如果我搜索Apple M1
作为结果我得到Orange M1
然后第三个或更多位置我得到Apple M-1
- 这是我存储的值,我假设应该是第一个!
我的问题是:有一种方法可以微调mysql搜索吗?
答案 0 :(得分:5)
改善MySQL自然语言模式搜索的最佳方法是使用Boolean Full-Text Searches代替。它将与自然语言模式搜索相同,但您可以使用其他修饰符来微调您的结果,例如:由
<强>&GT; &LT; 强>
这两个运算符用于更改单词对分配给行的相关性值的贡献。 &gt;运算符增加了贡献和&lt;运营商减少它。
有一个小的区别,布尔模式搜索不会根据相关性自动排序,所以你必须自己订购。
SELECT * FROM myTable
WHERE MATCH (name) AGAINST (">Apple M1" IN BOOLEAN MODE)
ORDER BY MATCH (name) AGAINST (">Apple M1" IN BOOLEAN MODE) desc
并注意:如果您与M-1
匹配,则两个版本的全文搜索都找不到M1
(即使最小字长设置为2)。它只会查找exakt(通常不区分大小写)单词匹配,它不会查找类似的单词(除非您使用*
)。它将“仅”通过某种算法权衡(精确)单词的组合,如果使用它们,则使用修饰符。
更新根据评论进行了一些额外的澄清:
如果您与Apple M1
匹配,则会按任意顺序返回包含(不区分大小写)Apple
或M1
的行,例如M1 apple
,Apple M4
,Apple M-1
和Orange M1
。它找不到Apples M4
或Orange M-1
,因为它们不完全是那个词。例如。 like '%M-1%'
也找不到Apple M1
。但是如果你愿意,你可以匹配Apple*
来查找Apple
和Apples
,但它总是在单词的末尾,*Apple*
是不可能的,你必须然后使用like '%Apple%'
。
这些行然后由评分算法排序,这将基本上对文本中较不常见的单词进行评分,而不是非常常见的单词。如果您添加>Apple
,则会为Apple
提供更高的值。它只是一个数字,您可以将它们添加到您的选择中,例如select ..., MATCH (name) AGAINST (">Apple M1" IN BOOLEAN MODE) as score
感受到这一点。
还有其他一些事情需要考虑:
只有具有最小长度的单词才会添加到索引中。该长度由innodb的innodb_ft_min_token_size
或myisam的ft_min_word_len
给出。所以你应该把它设置为例如2要包含M1
(否则,此单词对您的搜索不会产生任何影响。因为在您的示例中,您找到了Orange M1
,我认为它设置正确)。
-
通常被视为连字符。因此,您文本中的M-1
将分为两个单词M
和1
(根据您的最小单词长度设置可能包含也可能不包含,因此可能将其设置为1) 。您可以通过向字符集添加-
来更改该行为(请参阅Fine-Tuning MySQL Full-Text Search,以Modify a character set file
开头的部分),但如果您搜索,则不会再找到blue-green
blue
和/或green
。
全文搜索使用stopwords。这些单词不包含在您的索引中。此列表包含a
和i
,因此即使最小字长为1,您也找不到它们。您可以编辑该列表。
关于M1
/ M-1
潜在问题的一些想法。要根据您的具体要求进行调整,您必须添加有关搜索和数据的更多信息(可能是另一个问题),但有些想法:
您可以通过将两个版本都包含在搜索查询中来替换包含-
的用户输入:一次使用-
,但会在""
中包含,一次不包含Apple M-1
。因此,如果用户输入Apple M1 "M-1"
,您将创建搜索M1
(可以使用或不使用已修改的字符集,但没有新的字符集,您的最小字长必须为1)。如果用户输入M1 "M-1"
,您应检测到该内容并将其替换为match (name, clean_name) against ("M1" ...
。
另一种方法是使用干净的连字词保存其他列,并将该列添加到全文索引,然后where match(...) against(...) or product_id like 'M%1%'
。
你当然可以将喜欢和匹配结合起来,例如:如果您在输入中检测到产品编号,则可以使用where match(...) against(...) or product_id = 'M-1' or product_id = 'M1'
或where match(...) against(...) or name like '%M%1%'
甚至var info = JSON.parse(body); // Get File From Website
var itemforjson = item.market_hash_name; // Get The Item Name To Try To Use It In Json
depitems[i].value = parseInt(info.itemforjson); // Has To Be A Number
之类的内容,但后者可能会慢很多并且包含大量噪音。并且它可能无法正确评分,但至少它将在结果集中。
但正如我所说,这取决于您的数据和您的要求。