Firebase... Add/Update Firebase Using node.js Script

I have arbitrary JSON that is sensibly laid out like this:

[
  {
    "id":100,
    "name":"Buckeye, AZ",
    "status":"OPEN",
    "address":{
      "street":"416 S Watson RD",
      "city":"Buckeye"
      ...
    }
  }
]

I've written a node.js script like this for proof of concept (why I'm using node is that the JS API seems better supported than REST or Ruby for this. I could be wrong):

http = require('http')
Firebase = require('firebase')

all_sites_url = "http://supercharge.info/service/supercharge/allSites"
firebase_url  = "https://tesla-supercharger.firebaseio.com/"

http.get(all_sites_url, (res) ->
  body = ""
  res.on "data", (chunk) ->
    body += chunk
    return

  res.on "end", ->
    response = JSON.parse(body)
    all_sites = response
    send_to_firebase(response)
    return

  return
).on "error", (e) ->
  console.log "Got error: ", e
  return

send_to_firebase = (response) ->
  firebase_ref = new Firebase(firebase_url)

  for charger in response
    console.log charger
    new_child = firebase_ref.push()
    new_child.set {id: charger.id, data: charger}, (error) ->
      if error
        console.log "Data cound not be saved #{error}"
      else
        console.log "Data saved successfully"

The result is a unique id generated by Firebase, which has as a child a data and an id child. The data child has the expected information like name, status, etc.

What I'd prefer is to generate a key-value pair. E.g., for an id of 100:

- 100
    - name
    - address
      street
      city

etc. So my first question is how to accomplish this or if it is even sensible.

After the first time around, this data (call it the data from an external server) will be there and a mobile app will have added some fields. These are not present in the data already there. Next time I fetch data from the external server, I want to update things that have changed that the server would know about, like status. I don't want to tamper with things that only the mobile devices would know about like remote_observations.

I know I'm seeming a bit dense here, but I'm trying to put together a sensible data model that will be updatable from that server using a CRON job and incrementally updatable from a bunch of mobile devices.

Any help is much appreciated.

UPDATE: I have found that this works for getting the structure I want:

send_to_firebase = (response) ->
  firebase_ref = new Firebase(firebase_url)

  for charger in response
    firebase_ref.child(charger.id).update charger, (error) ->
      if error
        console.log "Data could not be saved #{error}"
      else
        responses_pending += 1
        console.log "Data saved successfully : #{responses_pending} pending"
        firebase_ref.on 'value', ->
          console.log "value received rp=#{responses_pending}"
          process.exit() if (responses_pending -= 1) < 1

So the code I settled on is this:

http = require('http')
Firebase = require('firebase')

firebase_url = '/path/to/your/firebase'

# code to get JSON of the form:
{
  "id":100,
  "name":"Buckeye, AZ",
  "status":"OPEN",
  "address":{"street":"416 S Watson RD",
            "city":"Buckeye",
            "state":"AZ",
            "zip":"85326",
            "country":"USA"},
   ... etc.
}

# Asynchronous get of JSON hash from some server or other.
get_my_fine_JSON().on 'complete', (response) ->
  send_to_firebase(response)

send_to_firebase = (response) ->
  firebase_ref = new Firebase(firebase_url)

  length = response.length

  for charger in response
    firebase_ref.child(charger.id).update charger, (error) ->
      if error
        console.log "Data could not be saved #{error}"
      else
        console.log "Data saved successfully"

      process.exit() if length -= 1 is 0

Discussion:

The idea was to have a Firebase structure like this:

- 100
  - address
    street: "123 Main Street"

etc.

That's reason 1 why id is pulled up to be the primary key. Reason 2 is so that I can uniquely identify an object pulled off the external server as the "same" one in my Firebase and apply any updates necessary.

Epiphany 1: Update is more like upsert. If the key is there, whatever hash you supply replaces matching values. If it's not there, then Firebase happily adds it. Which is way cool because it covers both the push and patch cases.

Epiphany 2: This process will hang waiting for events if nothing tells it to stop. That's why the countdown index, length is decremented until the code has upserted (for lack of a better term) each item.

Observation 1: Doing this in node.js is super fast compared with REST using Python or Ruby. And this upsert stuff is wicked cool if I'm understanding it right.

Observation 2: There isn't a ton of wisdom out there as of this writing regarding writing node shell scripts to do this kind of stuff. Maybe it's a good idea, maybe a bad one. I don't know.

Observation 3: Because of the asynchronous nature of node and the Firebase Javascript API (both GOOD THINGs), terminating a process before the last bit is done can be tricky because your process has to hang on just long enough to complete its last request/response with Firebase. This is, as mentioned before, done in the completion handler of the update. Otherwise we wouldn't necessarily be complete when the process exited.

Caveat 1: Related to observation 2, this could be a bad idea, but I haven't been able to find resources that speak to the problem.

Caveat 2: This could be a horrid abuse or misunderstanding of the Firebase update API. I am reporting observed behavior in the limited case of my specific data. YMMV.

Caveat 3: I'm hoping the process lifetime is as I suggest it is in observation 3.

A note to the decaffeinated: The Javascript for this is so trivially different that it shouldn't be too tough to translate. Or go to js2coffee and paste the Coffeescript into the right pane to get real Javascript in the left pane that you can tune.