火力地堡使许多人反规范化 [英] Firebase denormalizing many to many

查看:43
本文介绍了火力地堡使许多人反规范化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a pretty basic data structure

  • 事件
  • 主题

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

I would like to be able to easily show (query)

  1. 事件拥有什么主题

  1. what topics are owned by an event

涉及主题的事件

本月最受欢迎的主题

我对自己的事件结构很满意

I am pretty comfortable with my events structure like

/events/880088/topics.json *

["Firebase", "Cloud"]

但是我在如何构造/topics节点上很费劲.我部分地想到了使用

but I struggle with how to structure the /topics nodes. I partially get the idea of going with something like

/topics/Firebase

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

,然后,如果我更新事件的主题集合,则必须遍历所有/topics/节点并将/topics/{{topic}}/{{eventid}} 更新为{真实|空值}.似乎很伤脑筋.

and then if when I update an events's topic collection I would have to iterate over all the /topics/ nodes and update /topics/{{topic}}/{{eventid}} to {true | null}. Which seems rather ham fisted.

ALSO,那么我仍然不知道如何查询本月活动的主题.

ALSO, then I am still at a loss of how to query say, what are the topics covered by events this month.

示例JSBin,来自以下注释 http://jsbin.com/dumumu/edit?js,output

Example JSBin from comments below http://jsbin.com/dumumu/edit?js,output

* 我知道,我知道,数组是邪恶的,

* I know, I know, arrays are evil, https://www.firebase.com/blog/2014-04-28-best-practices-arrays-in-firebase.html, but I think they fit in this scenaris

推荐答案

以下是添加事件的一种方法:

Here's one way to add an event:

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);
  });
}

对我来说似乎很简单.有趣的是,您可以使用新的我们昨天发布的多位置更新(2015年9月):

Seems pretty simple for me. For an interesting twist, you can use the new multi-location updates we launched yesterday (September 2015):

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的一次写入操作,因此用户没有机会在两次写入操作之间关闭应用程序.

The latter is a bit more code. But it's a single write operation to Firebase, so there's no chance of the user closing the app between write operations.

您当然可以同时调用这两者:

You invoke both the same of course:

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数据库),通常必须调整数据结构以适合您要在其上进行的报告.

Querying/reporting

With Firebase (and most NoSQL databases), you typically have to adapt your data structure for the reporting you want to do on it.

安倍晋三在此问题上写了一个很好的答案,因此请务必阅读以下内容: Firebase数据结构必需的建议

Abe wrote a great answer on this recently, so go read that for sure: Firebase Data Structure Advice Required

如果您想更改现有事件的主题,此功能是完成此任务的一种方法:

If you want to change the topics for an existing event, this function is once way to accomplish that:

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);
  });
}

代码确实有点长,但这主要是为了

The code is indeed a bit long, but that's mostly to determine the delta between the current topics and the new topics.

如果您好奇的话,如果我们现在运行这些API调用:

In case you're curious, if we run these API calls now:

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
}

这篇关于火力地堡使许多人反规范化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆