我需要一些关于自然语言数据库的MongoDB模式设计的建议。
我需要存储每种语言文本和单词,如:
lang: {
_id: "English",
texts : [
{ text : "This is a first text",
date : Date("2011-09-19T04:00:10.112Z"),
tag : "test1"
},
{ text : "Second One",
date : Date("2011-09-19T04:00:10.112Z"),
tag : "test2"
}
],
words : [
{
word : "This",
},
{
word : "is",
},
{
word : "a",
},
{
word : "first",
},
{
word : "text",
},
{
word : "second",
},
{
word : "one",
}
]
}
然后我需要知道用户关联的每个单词和文本。单词/文本量往往很大,我需要列出语言中的所有单词以及用户为该语言关联的所有单词。
从我的角度来看,我认为存储与单词数组中给定单词相关联的user_id可能是一个很好的方法,如:
lang: {
_id: "English",
texts : [
...
],
words : [
{
word : "This",
users: [user1,user2,user3]
},
{
word : "is",
users: [user1,user2]
},
...
]
}
请记住,一个单词可以与数十万用户相关联,文档限制(我读过)是4MB,我需要:
这是一个好方法吗?或者你能想到一个更好的吗?
希望这个问题足够清楚,有人可以给我一个帮助;)
谢谢大家!
答案 0 :(得分:4)
我认为这不是一个好方法,因为你提到的原因是:文档大小限制。看起来你的方法,你肯定会遇到极限。我会采取更平坦的方法(这也应该使您的集合更容易查询)。像这样:
[
{
user: "user1",
word: "This",
lang: "en"
},
{
user: "user1",
word: "is",
lang: "en"
},
// et cetera...
]
换句话说,通过添加文档而不是水平地通过向一个文档添加更多数据来垂直增长。您可以使用 db.find({user:“user1”,lang:“en”}); 查询给定用户的单词。
当然,这种方法并非“规范化”,因此如果您关注空间,则可能需要为用户,单词和语言创建单独的集合,并通过ID在主集合中引用它们。但由于MongoDB中没有 join 查询,因此您必须权衡查询性能与空间效率。
答案 1 :(得分:1)
dbaseman是正确的(并且已经投票),但还有其他几点:
首先,在撰写本文时,文档限制现在为16MB(Max Document Size),假设您运行的是MongoDB的最新版本。
其次,无限增长在MongoDB中通常是一个坏主意,这种类型的文档大小扩展可能导致MongoDB必须移动文件,如果它超过分配给它的当前空间。您可以在文档的Padding Factor部分阅读更多相关信息。
这些类型的举动相对昂贵,特别是如果它们经常发生。因此,如果您确实采用这种类型的设计来限制主要集合(最新的X,最流行的X等)中的注释的大小(基本上限制了增长),甚至可能预先填充该文档字段(基本上)手动填充)超出平均大小将减少移动引起的添加/更改。
这就是为什么来自O'Reilly的MongoDB开发者提示和技巧书中的#6提示:
提示#6:不要嵌入具有未绑定增长的字段