我有歌曲和标签。标签可以是“记录位置”或“最后记录日期”类型。
在关系模型中,我会有一个包含song_id和tag_id信息的连接模型。但是在像indexeddb这样的文档库DB中,我会将标签及其信息直接存储在文档中。我想知道如果我没有很多独特的标签,那么从长远来看这不会导致DB bload吗?
如果另一首歌需要其中一个已经在另一首歌上使用的标签,我会有一个重复的标签。
我当然可以在这里使用连接商店,但这也包括2个表的手动提取。
我对该模型有几个问题:
我的主要方面是搜索标签值(并按类型过滤)。
答案 0 :(得分:1)
使用IDB和其他NoSQL存储的关键是不会陷入连接ID,只是试图让每个对象存储本身都有用。 (并且使用索引很好!)请记住,这就是SQL-ish数据库的工作原理,但它允许您在需要时进行专门的连接,而不是在一般情况下。
批量更新更具挑战性,但更多的是针对最常见的情况进行优化(显示查找歌曲/标签),而不是针对更稀有的事情进行优化(批量更改标签名称)
您正在考虑的最基本架构是将歌曲存储为:
{ name: "Name of Song"
id: <song id>
tags: ["tag1", "tag2", "tag3"] }
标签可以简单地用他们的名字来识别:
{ name: "tagname"
description: "Some tag description or whatever" }
首先创建你的歌曲对象商店:
var songs = db.createObjectStore("songs", "id");
然后创建一个multiEntry索引:
songs.createIndex("tags", "tags", {multiEntry: true});
然后创建一个标签objectStore:
var tags = db.createObjectStore("tags", "name");
现在你可以自己做联接,如果你真的需要,但有时它只是一些开关的东西。
var trans = db.transaction(["songs", "tags"]);
var songTags = [];
trans.objectStore("songs").get("songid").onsuccess = function(e) {
var song = e.target.result;
for (var i = 0; i < song.tags.length; i++) {
trans.objectStore("tags").get(song.tags[i]).onsuccess = function(e) {
var tag = e.target.result;
songTags.push(tag);
}
}
}
trans.oncomplete = function(e) {
showSongTags(songTags);
}
感谢歌曲上的'标签'索引,反之亦然。请注意,我们直接使用标记名称,而不是使用某些中间数字tag_id。
var trans = db.transaction(["songs", "tags"]);
var songs = [];
trans.objectStore("songs").index("tags").openCursor("tag1").onsuccess = function(e) {
var cursor = e.target.result;
if (!cursor) return;
cursor.continue();
songs.push(cursor.value);
}
trans.oncomplete = function(e) {
showSongs(songs);
}
答案 1 :(得分:0)
当他们不得不在像MySQL这样的关系数据库和像MongoDB这样的文档导向数据库之间做出选择时,你基本上面临着人们面临的同样问题。复制数据 - 更不用说密钥本身 - 占用空间,它肯定更像是“第三种形式”,可以存储一个副本并使用外键代替。
那就是说,我在我的IndexedDB工作中已经完成了这两个方面。相信你做的事情 - 关于存储效率 - 需要与你实际访问数据的方式进行权衡。当你想在IndexedDB中实现类似外键的模式时,它必然需要2个以上的对象存储,比如存储为底层文件系统上的两个独立文件。这意味着对于每个查询,您需要外键数据(此处为标签),您必须至少有两个对象存储点击,可能是两个事务,我假设,额外的io开销和这些相关联。
我会采用面向文档的方法,尝试使用关键速记等技巧(例如“n”代替“名称”)使存储命中率降低。