如何在Firebase中有效地存储和引用长的唯一字符串

时间:2014-10-01 19:11:30

标签: firebase firebase-realtime-database nosql

我想在Firebase表中存储链接。我希望它们是独一无二的。这些链接也将被其他表引用,因此我不希望每次引用它时都必须存储链接的整个长URL字符串。我无法找到一种强制链接唯一性的方法,同时还使用相对较短的密钥来引用它们。

例如,给定以下架构:

{
  "comments" : {
    "-JYC6EkXz5DZt7s5jFMT" : {
      "content" : "This is the first comment.",
      "createdAt" : 1412190501922,
      "link" : "http---testing-com-1-some-article",
      "userId" : 0
    },
    "-JYC6EmzCoKfYol1Ybyo" : {
      "content" : "This is a reply to the first.",
      "createdAt" : 1412190502079,
      "link" : "http---testing-com-1-some-article",
      "replyToCommentId" : "-JYC6EkXz5DZt7s5jFMT",
      "userId" : 1
    },
    "-JYC6Ep9lwdAwQbZmdYH" : {
      "content" : "This is a reply to the second.",
      "createdAt" : 1412190502218,
      "link" : "http---testing-com-1-some-article",
      "replyToCommentId" : "-JYC6EmzCoKfYol1Ybyo",
      "userId" : 0
    }
  },
  "links" : {
    "http---testing-com-1-some-article" : {
      "comments" : {
        "-JYC6EkXz5DZt7s5jFMT" : true,
        "-JYC6EmzCoKfYol1Ybyo" : true,
        "-JYC6Ep9lwdAwQbZmdYH" : true
      },
      "createdAt" : 1412190501880,
      "url" : "http://testing.com/1/some_article"
    }
  },
  "users" : [ {
    "comments" : {
      "-JYC6EkXz5DZt7s5jFMT" : true,
      "-JYC6Ep9lwdAwQbZmdYH" : true
    },
    "createdAt" : 1412190501881,
    "name" : "Joe Blow"
  }, {
    "comments" : {
      "-JYC6EmzCoKfYol1Ybyo" : true
    },
    "createdAt" : 1412190501881,
    "name" : "Jack Black"
  } ]
}

如您所见,每条评论必须包含其所属链接的长键。有没有一种很好的方法来缩短这些键,同时保持唯一性?

1 个答案:

答案 0 :(得分:1)

您是否有存储问题?如果没有,我不会因为优化而烦恼自己,因为复杂性可能不值得感知(并且可能是无形的)奖励。

要回答这个问题,一个简单,万无一失的方法就是为每个URL分配一个id并使用索引表进行查找。

var ref = new Firebase(URL);
var indexRef = ref.child('url_index');

function assignId(url) {
   var key = encodeURI(url);
   // create a new, unique id
   var uniqueId = indexRef.push().name();
   // store the id by URL
   indexRef.child(key).set(uniqueId);
}

function lookupId(url, callback) {
   var key = encodeURI(url);
   indexRef.child(key).once('value', function(snap) {
      // returns the unique id for this URL, or null if it does not exist yet
      callback(snap.val());
   });
}

更简单的方法是为每个URL创建一个唯一的哈希值并使用它来存储它们。这不是万无一失的,但在人类使用的规模上(即记录少于数十亿),这是非常独特的。

这里的好处是,当您拥有URL时,您不需要进行查找。您可以将其哈希以获取其密钥,然后执行您想要的任何操作(包括检查它是否唯一或获取实际URL)。

// taken from: http://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript-jquery
function hashCode(string) {
  var hash = 0, i, chr, len;
  if (string.length == 0) return hash;
  for (i = 0, len = string.length; i < len; i++) {
    chr   = string.charCodeAt(i);
    hash  = ((hash << 5) - hash) + chr;
    hash |= 0; // Convert to 32bit integer
  }
  return hash;
};

var ref = new Firebase(URL);
var indexRef = ref.child('url_index');

function storeUrl(url) {
   var key = hashCode(url);
   // store the id by URL
   indexRef.child(key).set(url);
}

function getUrl(key, callback) {
   indexRef.child(key).once('value', function(snap) {
      // returns the url for a given hash code
      callback(snap.val());
   });
}