Firebase对许多人进行非规范化

时间:2015-09-25 15:15:47

标签: firebase

我有一个非常基本的数据结构

  • 事件
  • 主题

我希望能够轻松展示(查询)

  1. 活动拥有哪些主题

  2. 哪些事件涵盖主题

  3. 本月最受欢迎的主题是什么

  4. 我对我的事件结构很满意,比如

    /events/880088/topics.json *

    ["Firebase", "Cloud"]
    

    但我在如何构建/ topics节点方面很困难。我部分地想到了像

    这样的东西

    /主题/火力地堡

    {"12345":true,"88088":true}
    

    然后如果我更新事件的主题集合,我将不得不迭代所有/ topics /节点并将 / topics / {{topic}} / {{eventid}} 更新为{是的|空值}。这似乎相当火腿。

    此外,我仍然不知道如何查询说,本月活动涵盖的主题是什么。

    来自以下评论的示例JSBin http://jsbin.com/dumumu/edit?js,output

    *我知道,我知道,阵列是邪恶的,https://www.firebase.com/blog/2014-04-28-best-practices-arrays-in-firebase.html,但我认为它们适合这个场景

1 个答案:

答案 0 :(得分:2)

以下是添加活动的一种方式:

function addEvent(title, topics) {
  var event =ref.child('events').push({ title: title });
  topics.forEach(function(topic) {
    event.child('topics').child(topic).set(true);
    ref.child('topics').child(topic).child(event.key()).set(true);
  });
}

对我来说似乎很简单。有趣的是,您可以使用新的multi-location updates we launched yesterday(2015年9月):

function addEvent(title, topics) {
  var updates = {};
  var eventId = ref.push().key();
  updates['events/'+eventId+'/title'] = title;
  topics.forEach(function(topic) {
    updates['events/'+eventId+'/topics/'+topic] = true;
    updates['topic/'+topic+'/'+eventId] = true;
  });
  ref.update(updates);
}

后者是更多的代码。但它只是Firebase的一次写操作,因此用户无法在写操作之间关闭应用程序。

你当然也会调用两者:

addEvent('Learn all about Firebase', ['Firebase']);
addEvent('Cloudspin', ['Firebase', 'Google', 'Cloud']);

数据结构变为:

{
  "events": {
    "-K-4HCzj_ziHkZq3Fpat": {
      "title": "Learn all about Firebase",
      "topics": {
        "Firebase": true
      }
    },
    "-K-4HCzlBFDIwaA8Ajb7": {
      "title": "Cloudspin",
      "topics": {
        "Cloud": true,
        "Firebase": true,
        "Google": true
      }
    }
  },
  "topic": {
    "Cloud": {
      "-K-4HCzlBFDIwaA8Ajb7": true
    },
    "Firebase": {
      "-K-4HCzj_ziHkZq3Fpat": true,
      "-K-4HCzlBFDIwaA8Ajb7": true
    },
    "Google": {
      "-K-4HCzlBFDIwaA8Ajb7": true
    }
  }
}

查询/报告

使用Firebase(以及大多数NoSQL数据库),您通常必须根据要对其进行的报告调整数据结构。

Abe最近写了一篇很好的答案,所以请务必阅读:Firebase Data Structure Advice Required

更新:更改活动的主题

如果您想更改现有事件的主题,此功能只需一次即可完成:

function updateEventTopics(event, newTopics) {
  newTopics.sort();
  var eventId = event.key();
  var updates = {};
  event.once('value', function(snapshot) {
    var oldTopics = Object.keys(snapshot.val().topics).sort();
    var added = newTopics.filter(function(t) { return oldTopics.indexOf(t) < 0; }), 
        removed = oldTopics.filter(function(t) { return newTopics.indexOf(t) < 0; });
    added.forEach(function(topic) {
      updates['events/'+eventId+'/topics/'+topic] = true;
      updates['topic/'+topic+'/'+eventId] = true;
    });
    removed.forEach(function(topic) {
      updates['events/'+eventId+'/topics/'+topic] = null;
      updates['topic/'+topic+'/'+eventId] = null;
    });
    ref.update(updates);
  });
}

代码确实有点长,但主要是determine the delta between the current topics and the new topics

如果您感到好奇,我们现在就运行这些API调用:

var event = addEvent('Cloudspin', Date.now() - month, ['Firebase', 'Google', 'Cloud']);
updateEventTopics(event, ['Firebase', 'Google', 'GCP']);

changeEventTopics()来电将导致此update()

{
  "events/-K-93CxuCrFDxM6k0B14/topics/Cloud": null,
  "events/-K-93CxuCrFDxM6k0B14/topics/GCP": true,
  "topic/Cloud/-K-93CxuCrFDxM6k0B14": null,
  "topic/GCP/-K-93CxuCrFDxM6k0B14": true
}