我有一个数据库,里面全是亚洲字符填充的记录(中文、日语和韩语)以及拉丁字符填充的记录(英语、法语,随便你怎么说),我想对它们执行全文搜索。
MySQL 说:
Ideographic languages such as Chinese and Japanese do not have word delimiters. Therefore, the FULLTEXT parser cannot determine where words begin and end in these and other such languages. The implications of this and some workarounds for the problem are described in Section 11.8, “Full-Text Search Functions”.
第 11.8 节实际上没有提供解决方法,甚至没有提及问题。
那么,如何在混合字符数据库中对单个汉字的搜索进行排序? %LIKE% 会起作用,但它没有很好的相关性评级。我应该只计算一个角色在记录中出现的次数,然后以此为依据进行排名吗?我很感激你的任何建议。谢谢!
最佳答案
这取决于数据集的大小。如果我们谈论的是数十万行,我可能会看一下可用的优秀独立全文搜索解决方案之一。我实际上从来没有处理过这个问题 mysqlf,所以我不确定哪些解决方案包括对亚洲语言的支持。
不过我确实知道 lucene有中文、日文和韩文的分析器,所以我猜它对你正在做的事情有某种支持。当我需要将 lucene 与 php 集成时,我通常做的是将 lucene 实现为套接字服务器,并从 php 连接到它。
如果数据集足够小,则可以选择采用您自己的临时方法。这个问题有两个部分:检索要排名的文档和实际排名。有几种方法可以进行检索。如果您的数据集足够小,一种可能是使用 LIKE。另一种可能是推出您自己的基于磁盘的索引方案,尽管这会相当复杂且耗时。您还可以使用 MySQL 作为中间路径,如下所述。
为了使用 MySQL 实现索引方案,您必须创建一些具有以下结构的表:
document
document_id
document_text
document_tokencount
document_token
document_id
token_id
token_docfrequency
index (token_id, document_id)
token
token_id
token_unicode
token_globalfrequency
index (token_unicode)
然后我将处理每个文档并在 document_token 表中为文档中的每个字符(标记)插入一行。 token_unicode 字段将包含用于引用此字符的整数 unicode 序列。 token_docfrequency 字段包含一个整数,对应于文档包含该标记的次数,而 token_globalfrequency 字段包含该术语在所有文档中使用的总次数。
这将允许您快速搜索 token :
SELECT * FROM document_token WHERE token_id = 1
UNION
SELECT * FROM document_token WHERE token_id = 2
UNION
SELECT * FROM document_token WHERE token_id = 3
(联合方法是一种 hack,它允许 mysql 对所有选择使用索引,并且很可能比使用单个选择和多个 or 语句的相应查询更快)
剩下的问题就是相关性排名,这正是您真正要求的。 :) 这可以通过利用 Vector Space Model (VSM) 来完成并取得相当好的结果。 .
完成搜索后,您要做的第一件事就是计算 tf-idf这个 token 的分数。这是使用以下公式完成的:
tf-idf = tf(t,d) / tf(d) * log(D / d(t))
where:
tf(t,d) = token frequency in current document
tf(d) = total number of tokens in current document
D = total number of documents
d(t) = number of document that contains the token
首先为搜索查询中的每个术语计算此分数,并将结果存储在 HashMap 或类似的东西中。这是您的第一个向量,称为 v_1。然后继续第一个文件。同样计算文档中每个术语的 tf-idf 分数,并将其存储为 v_2。现在您可以使用 cosine similiarity 计算此文档的分数:
score = arccos(v_1 * v_2 / (|v_1| * |v_2|))
结果是一个可用于对文档进行排名的值。继续对每个文档执行此操作。将它们按降序排列。列表中的第一个文档将是最相关的文档。
这听起来可能有点复杂,但如果您对线性代数有一些基本了解,您可能会在几个小时内得出一个可行的解决方案。不过,如果可能的话,请使用现有的解决方案,例如 Lucene。
关于MySQL 全文搜索表意(亚洲)字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/817080/
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
在我的Rails(2.3,Ruby1.8.7)应用程序中,我需要将字符串截断到一定长度。该字符串是unicode,在控制台中运行测试时,例如'א'.length,我意识到返回了双倍长度。我想要一个与编码无关的长度,以便对unicode字符串或latin1编码字符串进行相同的截断。我已经了解了Ruby的大部分unicode资料,但仍然有些一头雾水。应该如何解决这个问题? 最佳答案 Rails有一个返回多字节字符的mb_chars方法。试试unicode_string.mb_chars.slice(0,50)
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我有一大串格式化数据(例如JSON),我想使用Psychinruby同时保留格式转储到YAML。基本上,我希望JSON使用literalstyle出现在YAML中:---json:|{"page":1,"results":["item","another"],"total_pages":0}但是,当我使用YAML.dump时,它不使用文字样式。我得到这样的东西:---json:!"{\n\"page\":1,\n\"results\":[\n\"item\",\"another\"\n],\n\"total_pages\":0\n}\n"我如何告诉Psych以想要的样式转储标量?解
在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg