3

Some background:

My question is very similar to this clarification question about denormalization, but I want to change the situation a bit.

In the Considerations section of this blog post on denormalization, the Firebase people say the following about updating data.

Let’s discuss some consequences of a [denormalized data structure]. You will need to ensure that every time some data is created (in this case, a comment) it is put in the right places.

The example includes three paths, one to store the comment's data, and two paths under which to store pointers to that comment.

...

Modification of comments is easy: just set the value of the comment under /comments to the new content. For deletion, simply delete the comment from /comments — and whenever you come across a comment ID elsewhere in your code that doesn’t exist in /comments, you can assume it was deleted and proceed normally:

But this only works because, as the answer to the other question says,

The structure detailed in the blog post does not store duplicate comments. We store comments once under /comments then store the name of those comments under /links and /users. These function as pointers to the actual comment data.

Basically, the content is only stored in one location.

The question:

What if the situation were such that storing duplicate data is necessary? In that case, what is the recommended way to update data?

My attempt at an answer:

An answer to this question exists, but it is directed at MongoDB, and I'm not sure it quite addresses the issue in Firebase.

The most sensible way I could think of, just for reference, is as follows.

I have a helper class to which I give a catalog of paths in Firebase, which somewhat resembles a schema. This class has methods that wrap Firebase methods, so that I can perform writes and updates under all the paths specified by my schema. The helper class iterates over every path where there is a reference to the object, and at each location performs a write, update, or delete. In my case, no more than 4 paths exist for any individual operation like that, and most have 2.

Example:

Imagine I have three top-level keys, Users, Events, and Events-Metadata. Users post Images to Events, and both Events and Users have a nested record for all their respective Images. Events-Metadata is its own top-level key for the case where I want to display a bunch of events on a page, but I don't want to pull down potentially hundreds of Image records along with them.

Images can have captions, and thus, when updating an Image's caption, I should update these paths:

new Firebase("path/to/eventID/images/imageID/caption"), and
new Firebase("path/to/userID/images/imageID/caption")

I give my helper class both those of these paths and a wrapper method, so that anytime a caption is updated, I can call helperclass.updateCaption(imageObj, newCaptionData), and it iteratively updates the data at each path.

Images are stored with attributes including eventID, userID, and imageID, so that the skeletons of those paths can be filled in correctly.

Is this a recommended and/or appropriate way to approach this issue? Am I doing this wrong?

Community
  • 1
  • 1
aidan
  • 1,627
  • 17
  • 27
  • 1
    I can't think of a case in the past where storing duplicate data (other than an index of keys) has been necessary. It seems like you simply need a `user/` path, `event/` path, a `captions/` path, and an `images/` path. You may need an index of image keys under your user path and possibly events, but unlikely. Can you explain why this was ruled out? – Kato Sep 30 '14 at 02:32
  • It perhaps stems from a misunderstanding of The Blog Post, but the intended convenience was to have common groupings of data grouped together as part of our larger data structure. A User's uploaded Images, and Images attached to an Event, are probably our two most frequent queries; we're also in Angular (thus AngularFire), and so the thought was to have both of those categories bundled up for ease of use with ng-repeat / AngularFire Arrays. I.e. `$firebase(new Firebase(BASE_URL + "events/EVENTID/images")).$asArray()` => straight into ng-repeat as a $scope variable. Does that make sense? – aidan Oct 01 '14 at 00:18
  • I would still start with attempting an images/ path and just store an index to the images in your other areas (e.g. events/$eventid/images/$imageid/true). – Kato Oct 02 '14 at 15:55
  • You make the sense. That's what we'll do. Thank you (!!!) for taking the time. – aidan Oct 03 '14 at 16:54
  • 1
    This SO post covers examples of storing duplicate, denormalized data, and offers various methods for making updates to said data: http://stackoverflow.com/questions/30693785/how-to-write-denormalized-data-in-firebase – Scott Coates Jul 14 '15 at 04:05

0 Answers0