1
\$\begingroup\$

I'm new to Firebase and am a recovering SQL developer, so I haven't quite wrapped my mind around all aspects of firebase querying. I have an app that has basic functionality in place, but some aspects run quite slowly.

For example, I have a function that gets cities for a dropdown based off two other dropdowns (country and province). If I query for Canada/Alberta, it will find 1155 cities, but takes 4-5 painful seconds to do so.

Does anyone have any refactoring advice to make this quicker? I use a once query because the data won't change, and I need to tag lat/lon into the value to be able to use it in a search based off what the user chooses.

Query:

function loadCity() {

//GET ID OF COUNTRY CURRENTLY SELECTED
var countryID = $("#inlineFormCountry option:selected").val();
//console.log("countryID:" +countryID);

//GET ID OF PROVINCE CURRENTLY SELECTED
var provinceID = $("#inlineFormProvinceState option:selected").val();
//console.log("provinceID:" + provinceID);

// GET A REFERENCE TO THE CITY NODE
var refCity = firebase.database().ref('baseData/mapping/countries/' + countryID + '/provinces/' + provinceID + '/cities').orderByChild('nameCity');

document.getElementById("inlineFormCity").innerHTML = "";

var itemCount = 0;

refCity.once('value', function(snapshot) {
    var recordCount = snapshot.numChildren();
    document.getElementById("rowCount").innerHTML = recordCount + " city records found.";
    snapshot.forEach(function(childSnapshot) {
        itemCount += 1;

        iKey = childSnapshot.key;
        //console.log(iKey);

        childData = childSnapshot.val();
        //console.log(childData);

        var nameCity = childData.nameCity;
        var textLatitude = childData.textLatitude;
        var textLongitude = childData.textLongitude;

        iKey = iKey + "," + textLatitude + "," + textLongitude

        if (itemCount == 1) {
            document.getElementById("inlineFormCity").innerHTML = "<option selected value='" + iKey + "'>" + nameCity + "</option>"
            document.getElementById("nameCity").value = nameCity;
            document.getElementById("textLatitude").value = textLatitude;
            document.getElementById("textLongitude").value = textLongitude;
        } else {
            document.getElementById("inlineFormCity").innerHTML = document.getElementById("inlineFormCity").innerHTML + "<option value='" + iKey + "'>" + nameCity + "</option>"
        };

        if (itemCount == recordCount) {};
    });
});

};

Relevant indexing from rules:

"baseData": {
  "mapping": {
    "countries": {
      "$countryID": {
      ".indexOn": "nameCountry",
      "provinces": {
      "$provinceID": {
        ".indexOn": "nameProvince",
        "cities": {
        "$cityID": {
          ".indexOn": "nameCity"            
                    }
                }
            }
        }
        }
\$\endgroup\$
  • \$\begingroup\$ From a data structure perspective your approach already looks pretty good. The biggest cost when accessing the Firebase is building the initial connection (once per app/page). After that the cost is little more than latency + data size / bandwidth. Are you downloading a lot of data for each city? \$\endgroup\$ – Frank van Puffelen Feb 10 '17 at 15:20
  • \$\begingroup\$ Thanks Frank, glad to know I'm on the right path. The only data in each city entry is name, lat and lon. You did mention that the initial connection is only needed once per page, and maybe that's where I'm going wrong. I'll dig into maybe cleaning up the connections. Thanks for the lead! \$\endgroup\$ – Adam Till Feb 10 '17 at 18:54
  • \$\begingroup\$ If it stays slower than you expect, set up a jsbin that reproduces the problem and I'll have a look. \$\endgroup\$ – Frank van Puffelen Feb 10 '17 at 19:35
  • \$\begingroup\$ Thanks tons for the offer, and the idea (I'd upvote if I could...seem to be too new to do so). \$\endgroup\$ – Adam Till Feb 10 '17 at 19:45
  • \$\begingroup\$ I seem to have made a huge improvement by using only one var ref = firebase.database().ref(); for the page, but also by storing the dropdown items in a var and only loading on the last item. By constantly appending items using the getElementByID call it seemed much slower. Between the two it's running much cleaner. Obliged! \$\endgroup\$ – Adam Till Feb 10 '17 at 19:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.