Skip to content
This repository was archived by the owner on Mar 17, 2025. It is now read-only.

FirebaseExtended/parse-migration-tools

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Parse Migration Tools

Status

Status: Archived

This library is no longer actively maintained. We do not recommend using this library in production.

If you maintain a fork of this library that you believe is healthier than the official version, we may consider recommending your fork. Please open a Pull Request if you believe that is the case.

Introduction

This is a set of code to help you think about migrating from Parse to Firebase. This project complements the talk "Migrate to Firebase" from Google I/O and the Parse migration guide for Firebase. For additional information see:

We intend to cover the following areas with code tools. Checked sections are ready for use:

  • Migrate Parse Data to Firebase using Cloud Code.
  • Migrate Users from Parse Social to Firebase Auth client-side.
  • Migrate devices from Parse Push to Firebase Notifications by keeping Parse channels in sync with Firebase topics.
  • Guides for using Firebase Storage to back your Parse Files.

Parse Data

The Firebase and Parse data models are very different. You will build a cleaner app if you start by thinking about how your app's data would be laid out if it were written on Firebase from the beginning. Once you know how your natural Firebase structure would look, you can probably describe how an individual ParseObject would map to the Firebase Realtime Database. We offer two files to help you migrate from Parse:

  1. migrator.js A tool that allows you to keep your existing Cloud Code and use Cloud Code to migrate data out of Parse.
  2. firebase-rest.js A simple wrapper that helps you talk to Firebase in Cloud Code (where the Firebase Node module doesn't work).

Imagine you have a BlogPost class in Parse with the following fields:

  • title (String) Name the post
  • body (String) Blog contents
  • keywords (String) Originally you chose to do text searches on a space separated list
  • keywords_list (Array) You realized later that Parse can search an array better and added Cloud Code to put keywords into keywords_list

You probably have Cloud Code like:

Parse.Cloud.beforeSave('BlogPost', function(request, response) {
  var object = request.object;
  if (object.isDirty('keywords_list')) {
    response.error('keywords_list is managed by Cloud Code only');
    return;
  }
  object.set('keywords_list', object.get('keywords').split(' '));
  response.success(object);
}

A logical structure for your blog posts in Firebase might look like:

{
  "posts": {
    "aBlogPostID": {
      "title": "Firebase expands to become a unified app platform",
      "body": "Eighteen months ago, Firebase joined Google...",
      "keywords": ["googleio", "announcements"],
    },
  },
  "keywords": {
    "googleio": {
      "aBlogPostID": true,
      "anotherBlogAboutGoogleIO": true
    },
    "announcements": {
      "aBlogPostID": true
    }
  }
}

A few things are noticeably different in this structure:

  1. We no longer use the legacy "keywords" string. "keywords" in Firebase is the value of "keywords_list" in Parse.
  2. The values from "keywords_list" are stored in a different location so we can look up blogs related to a "googleio" by reading the keys under "/keywords/googleio". We also have "keywords" inside the blog post. This lets us clean up a blog post by knowing all of its references under "keywords" and lets us display a blog post's keywords inline if we want.

Migrator can help us do this very easily in 3 steps:

  1. Change our Parse.beforeSave to a Migrator.beforeSave. This is the same except it works with promises instead of callbacks.
  2. Describe how we would copy an object from Parse to Firebase
  3. (optional) Describe how we translate a Parse object deletion to Fireabse

We would do this with the following Cloud Code:

var _ = require('underscore');
var migrator = require('cloud/migrator.js')(Parse);
var ref = require('cloud/firebase.js')({
  url: 'https://my-firebase-database-url.firebaseio.com',
  key: 'if-my-firebase-database-is-secured-this-key-gives-me-admin-access',
  parse: Parse
});

// Notice this is almost the same (and actually a bit simpler) than the original beforeSave
migrator.beforeSave('BlogPost', function(request) {
  var object = request.object;
  if (object.isDirty('keywords_list')) {
    throw 'keywords_list is managed by Cloud Code only';
  }
  object.set('keywords_list', object.get('keywords').split(' '));
  return object;
}

// When an object is created, this is run just after the afterSave (we need a second pass
// to get an object ID). When the object is modified, this is run between beforeSave and
// afterSave.
migrator.migrateObject('BlogPost', function(object) {
  // We're setting the full object
  var saveObject = ref.child('posts').child(object.id).put({
    title: object.get('title'),
    body: object.get('body'),
    keywords: object.get('keywords')
  });
  
  // But using a deep update to only adjust keywords
  var keywordsUpdate = {};
  _.each(object.get('keywords'), function(keyword) {
    keywordsUpdate['keywords/' + keyword + '/' + object.id] = true;
  });
  
  return Parse.Promise.when(saveObject, ref.patch(keywordsUpdate));
});

// This is run between beforeDelete and afterDelete.
migrator.migrateDelete('BlogPost', function(object) {
  // Setting a value to null in Firebase deletes it
  var updates = {};
  _.each(object.get('keywords'), function(keyword) {
    updates['keywords/' + keyword + '/' + object.id] = null;
  });
  updates['posts/' + object.id] = null;
  return ref.patch(updates);
});

// generate Parse.Cloud triggers.
migrator.exportTriggers();

This will ensure all changes that happen on your old app get translated to Firebase. This will create a beforeSave and afterSave trigger for BlogPost as well as a Cloud Job called "import". Schedule this job to run every 15 minutes to automatically migrate all data from Parse into Firebase.

In new versions of your app, you should make sure that writes to Parse (either from the Firebase backend or from an app that dual-writes to Parse and Firebase) sets migrationStatus to 1 in Parse to short-circuit the migration logic.

Parse Files

Parse has not yet decided how they plan to migrate Parse Files to other backends (discussion). When they do, we expect they will continue with their plan to support Google Cloud Storage.

Parse Server already supports Google Cloud Storage, and there's an adapter that lets you do this. Because Firebase Storage is built on top of Google Cloud Storage, this means you can use one backend for both your Parse Files and Firebase Storage.

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •