Mysql 在RDBMS中存储uni/bi/Trigram和ngrams的正确方法?
我有一个单字、双字和三字的列表,我从一堆文档中提取了这些单字。我的目标是一个静态分析报告,也是一个我可以在这些文档上使用的搜索Mysql 在RDBMS中存储uni/bi/Trigram和ngrams的正确方法?,mysql,sql,postgresql,rdbms,n-gram,Mysql,Sql,Postgresql,Rdbms,N Gram,我有一个单字、双字和三字的列表,我从一堆文档中提取了这些单字。我的目标是一个静态分析报告,也是一个我可以在这些文档上使用的搜索 John Doe Xeon 5668x corporate tax rates beach tax plan Porta San Giovanni ngrams按日期和文件进行标记。例如,我可以找到大字组之间的关系,以及它们的短语首次出现的时间,以及文档之间的关系。我还可以搜索包含X个un/bi/trigram短语的文档 所以我的问题是如何存储它们来优化这些搜索 最简
John Doe
Xeon 5668x
corporate tax rates
beach
tax plan
Porta San Giovanni
ngrams按日期和文件进行标记。例如,我可以找到大字组之间的关系,以及它们的短语首次出现的时间,以及文档之间的关系。我还可以搜索包含X个un/bi/trigram短语的文档
所以我的问题是如何存储它们来优化这些搜索
最简单的方法是为每个短语创建一个简单的字符串列,然后每次在文档中找到该单词/短语时,我都会将关系添加到document_ngram表中
table document
{
id
text
date
}
table ngram
{
id
ngram varchar(200);
}
table document_ngram
{
id
ngram_id
document_id
date
}
然而,这意味着,如果我想通过三角形搜索单个单词,我必须使用字符串搜索。例如,假设我想要所有有“夏天”字样的三叉树
因此,如果我将单词拆分,使存储在ngram中的唯一内容是一个单词,然后添加三列,以便所有1、2和3个单词链都可以放入文档ngram
table document_ngram
{
id
word1_id NOT NULL
word2_id DEFAULT NULL
word3_id DEFAULT NULL
document_id
date
}
这是正确的方法吗?他们有更好的方法吗?我目前正在使用PostgreSQL和MySQL,但我相信这是一个通用的SQL问题。这就是我如何为数据建模(注意,“the”被引用了两次)您还可以为单个单词添加权重
DROP SCHEMA ngram CASCADE;
CREATE SCHEMA ngram;
SET search_path='ngram';
CREATE table word
( word_id INTEGER PRIMARY KEY
, the_word varchar
, constraint word_the_word UNIQUE (the_word)
);
CREATE table ngram
( ngram_id INTEGER PRIMARY KEY
, n INTEGER NOT NULL -- arity
, weight REAL -- payload
);
CREATE TABLE ngram_word
( ngram_id INTEGER NOT NULL REFERENCES ngram(ngram_id)
, seq INTEGER NOT NULL
, word_id INTEGER NOT NULL REFERENCES word(word_id)
, PRIMARY KEY (ngram_id,seq)
);
INSERT INTO word(word_id,the_word) VALUES
(1, 'the') ,(2, 'man') ,(3, 'who') ,(4, 'sold') ,(5, 'world' );
INSERT INTO ngram(ngram_id, n, weight) VALUES
(101, 6, 1.0);
INSERT INTO ngram_word(ngram_id,seq,word_id) VALUES
( 101, 1, 1)
, ( 101, 2, 2)
, ( 101, 3, 3)
, ( 101, 4, 4)
, ( 101, 5, 1)
, ( 101, 6, 5)
;
SELECT w.*
FROM ngram_word nw
JOIN word w ON w.word_id = nw.word_id
WHERE ngram_id = 101
ORDER BY seq;
结果:
word_id | the_word
---------+----------
1 | the
2 | man
3 | who
4 | sold
1 | the
5 | world
(6 rows)
现在,假设您要在现有(6克)数据中添加4克:
其他结果:
INSERT 0 2
INSERT 0 1
INSERT 0 4
word_id | the_word
---------+----------
1 | the
2 | man
6 | is
7 | lost
(4 rows)
顺便说一句:向该模型添加文档类型对象将向该模型添加两个附加表:一个用于文档,另一个用于document*ngram。(或者在另一种方法中:对于document*word)递归模型也是一种可能
更新:上面的模型需要一个额外的约束,需要实现触发器(或规则+额外的表)。伪代码:
ngram_word.seq >0 AND ngram_word.seq <= (select ngram.n FROM ngram ng WHERE ng.ngram_id = ngram_word.ngram_id)
ngram_word.seq>0和ngram_word.seq一个想法是稍微修改一下原始的表布局。考虑NGRAM VARCHAR(200)列仅包含NGRAM的1个字,添加WordNoNO(1, 2,或3)列,并添加到分组列中,以便例如,在二元RAM中的两个字的两个记录相关(给它们相同的WorddGROUP)。[在甲骨文中,我会从序列中提取单词\u组号
——我想PostGres也会有类似的东西)
“document_ngram”的最后一个版本包含一个重复组。您需要一个额外的表来避免这种情况。(第二个版本将重复组放入字符串中,这更糟)@wildplasser,“重复组”是什么意思?1NF:word1\u id、word2\u id、word3\u id本质上是一个数组。使用非关系数据库可能会有更好的结果-您考虑过这个选项吗?本教程可能很相关,它使用了MySQL
和R
:不错。这是存储单词的正确方法,因此它们不会重复,也很容易查询。单词是实体。ngram是实体。文档是实体。其余的是实体之间的关系。我正在尝试解决这个问题。ngram表上的权重列是什么?既然我需要将ngram链接到文档,我会添加一个文档ngram表,其中包括日期、ngram单词id、文档id
,并修改ngram单词
表t吗o还有主键吗?另外,word\u id
&ngram\u id
在现实生活中是一个序列,对吗?权重列是未使用的有效载荷,但我用它来显示如何存储ngram的属性(在大多数情况下:权重或频率)。文档表只是层次结构中的另一层:文档指的是单词和/或ngram。文档还可以包含一些摘要信息(如有效性、重要性等),是的,单词id和ngram id可以是序列。(但它们也可以指由程序/数据库外的另一个进程强加的编号)
ngram_word.seq >0 AND ngram_word.seq <= (select ngram.n FROM ngram ng WHERE ng.ngram_id = ngram_word.ngram_id)
table document
{
id
text
date
}
table ngram
{
id
word_group
word_no
ngram varchar(200);
}
table document_ngram
{
id
ngram_id
document_id
date
}