1

我有歌曲和标签。标签可以是“记录位置”或“最后记录日期”之类的类型。

在关系模型中,我将有一个包含 song_id 和 tag_id 信息的连接模型。但是在像 indexeddb 这样的文档库数据库中,我会将标签及其信息直接存储在文档中。我想知道如果我没有很多独特的标签,从长远来看,这是否不会导致 DB bload?

如果另一首歌曲需要其中一个标签,而该标签已在另一首歌曲中使用,我将有一个重复的标签。

我当然也可以在这里使用连接存储,但这也包括手动获取 2 个表。

我对模型有几个问题:

  1. 我应该有歌曲和标签商店吗?
  2. 附加到每首歌曲的标签的批量更新是如何执行的?
  3. 我可能需要哪些指标才能做到这一点?

我的主要方面是通过标签值搜索(并按类型过滤)。

4

2 回答 2

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" }

首先创建你的歌曲 objectStore:

var songs = db.createObjectStore("songs", "id");

然后创建一个多条目索引:

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);
}
于 2012-09-20T21:18:03.327 回答
0

当人们不得不在像 MySQL 这样的关系数据库和像 MongoDB 这样的面向文档的数据库之间进行选择时,您基本上面临同样的问题。复制数据 - 更不用说键本身 - 占用空间,并且存储一个副本并使用外键肯定更“第三种形式”。

也就是说,我在我的 IndexedDB 工作中经历了这两个方面。相信你所做的事情——关于存储效率——需要与你实际访问数据的方式进行权衡。当您想在 IndexedDB 中实现类似外键的模式时,它必然需要 2 个以上的对象存储,例如在底层文件系统上存储为两个单独的文件。这意味着对于您需要外键数据(此处为标签)的每个查询,您必须至少有两个对象存储命中,可能是两个事务,并且,我假设,额外的 io 开销以及与这些相关的开销。

我会采用面向文档的方法,并尝试使用诸如键速记之类的技巧(例如“n”而不是“name”)来减少对存储的严重影响。

于 2012-03-23T02:45:07.750 回答