How to insert data into Firebase using Polymerfire

2020-03-06 08:02发布

问题:

My use case is that I have an <iron-form> with a single <paper-textarea> field that accepts a string list of email addresses which I parse into an array, then I want to:

  1. Store the individual email addresses in my Firebase (for indexing and lookup purposes),
  2. at multiple locations (per data fan out technique),
  3. with a single write operation (because I don't want to make 100 API calls if the list is that long) and
  4. without overwriting any existing data.

Specifically, I want to start with State A, as follows:

State A
my-app
 |
 - emails
 |  |
 |  - email1@example,com
 |     |- old: "data"
 |  - email2@example,com
 |     |- old: "data"
 - users
    |
    - c0djhbQi6vc4YMB-fDgJ

And achieve State B as follows:

State B
my-app
 |
 - emails
 |  |
 |  - email1@example,com
 |     |- old: "data"
 |  - email2@example,com
 |     |- old: "data"
 |  - email3@example,com
 |     |- new: "data"
 |  - email4@example,com
 |     |- new: "data"
 - users
    |
    - c0djhbQi6vc4YMB-fDgJ
       |
       - emails
          |
          - email3@example,com
             |- new: "data"
          - email4@example,com
             |- new: "data"

Notice: The {old: "data"} is not overwritten.

Background

I seek to extend this SO question and answer.

There, we inserted a single node in a new location with three options:

  1. using firebase-query
  2. JS SDK
  3. using firebase-document

Now, I need to do the same type of insertion (without deletion or replacing old data) for multiple nodes (with a user defined, not autogenerated, key; i.e., keys are specific email addresses). I also need to use the data fan out technique to update multiple paths with a single write operation.

Similar to what's shown here.

https://firebase.google.com/docs/database/web/read-and-write#update_specific_fields
function writeNewPost(uid, username, picture, title, body) {
  // A post entry.
  var postData = {
    author: username,
    uid: uid,
    body: body,
    title: title,
    starCount: 0,
    authorPic: picture
  };

  // Get a key for a new Post.
  var newPostKey = firebase.database().ref().child('posts').push().key;
  // * * * * * * * * * * * * * * * *  
  // THE ABOVE LINE NEEDS TO CHANGE TO SUPPORT USER-GENERATED KEYS SUCH AS EMAIL ADDRESSES
  // * * * * * * * * * * * * * * * * 

  // Write the new post's data simultaneously in the posts list and the user's post list.
  var updates = {};
  updates['/posts/' + newPostKey] = postData;
  updates['/user-posts/' + uid + '/' + newPostKey] = postData;

  return firebase.database().ref().update(updates);
}

Also note, one of the comments mentions:

There's no reason newPostKey above couldn't be an email address...

The challenge is that I need to write multiple keys to multiple locations simultaneously in a single call.

回答1:

The Firebase Realtime Database supports arbitrarily complex atomic deep updates (blog post). It works like so:

  1. You can update any arbitrarily deep path with a single .update() call
  2. The full path on the key side of your update map will be replaced, so you must address subkeys directly if you don't want to blow away the parent
  3. Paths are relative to your current ref

So let's take your example:

var update = {};

update['emails/email3@example,com'] = {new: 'data'};
update['emails/email4@example,com'] = {new: 'data'};
update['users/c0djhbQi6vc4YMB-fDgJ/emails/email3@example,com'] = {new: 'data'};
update['users/c0djhbQi6vc4YMB-fDgJ/emails/email4@example,com'] = {new: 'data'};

firebase.database().ref().update(update);

This will update all of the locations simultaneously. To make it dynamic, simply use string interpolation when constructing the keys.