-1

Given

The url root is: https://myApp.firebaseio.com

And

The data is:

  {
    "users": {
      "u00001": {
        "name": "Andy",
        "teams": {
           "t001": true,
           "t003": true
        }
      },
      ...
    },
    "teams": {
      "t001": {
        "name": "Alpha Team"
      },
      "t002": {
        "name": "Beta Team"
      },
      "t003": {
        "name": "Gamma Team"
      },
      ...
    }
  }

And

The teams Andy joins are ['t001', 't003']

Question:

Is it possible to use ONE query to get all the names of the teams that Andy joins? (find all the team names, where IDs are in ['t001', 't003'], e.g. expect ["Alpha Team", "Gamma Team"] )

Thanks in advance.

Max
  • 1,064
  • 9
  • 23
  • Did you write any code yet? What are you having problems with? – Frank van Puffelen Mar 27 '16 at 18:40
  • Please advise what I need to do to prove that I have already tried. I have to admit I'm not good at elasticsearch if it can easily solve my problem. At the moment I need a loop with the 2 team IDs to execute 2 fetches. e.g. new Firebase("https://myApp.firebaseio.com/teams/" + teamId).on("value", function(data){ ... }). – Max Mar 27 '16 at 18:52
  • I don't doubt you've been working on this for a while, but your questions don't reflect that effort. You should at the very least be able to build a query with the information in the [Firebase documentation on queries](https://www.firebase.com/docs/web/guide/retrieving-data.html#section-complex-queries). The fact that you cannot get your query to work, we can help with. – Frank van Puffelen Mar 27 '16 at 18:58

2 Answers2

2

This should work:

var ref = new Firebase('https://myApp.firebaseio.com');
ref.child('users/u00001/teams').on('value', function(teamKeys) {
  var teamNames = [];
  teamKeys.forEach(function(teamKey) {
    ref.child('teams').child(teamKey.key()).once('value', function(teamSnapshot) {
      teamNames.push(teamSnapshot.val().name);
      if (teamNames.length == teamKeys.numChildren()) {
        console.log('All team names loaded');
      }
    }); 
  });
})

If you're worried about the loading time and number of round-trips, see Speed up fetching posts for my social network app by using query instead of observing a single event repeatedly

Community
  • 1
  • 1
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thanks for the if statement: if (teamNames.length == teamKeys.numChildren()) { ... }. I can resolve the promise in it. – Max Mar 27 '16 at 19:07
  • Yup. But I hope you also realize that if that was the only part you were asking about, the rest of this code should've been in your question. – Frank van Puffelen Mar 27 '16 at 19:48
  • That's an extra benefit I get from your answer, and thanks. I'm after ONE query to get the result, without relying on a loop on the client side with promises. And I still haven't found the answer. (I know how to do a between filter by using the startAt(text).endAt(text), but I can't find a good solution for a in-list filter) – Max Mar 27 '16 at 20:22
  • The only way to get the data in a minimal, single read is to store the information you want in a single location. There is no magical other way. But the above approach is fast enough. If you still think otherwise, read the linked answer again... and again... and again. If instead you are having trouble translating it into a Promise, post what *you* have tried. – Frank van Puffelen Mar 27 '16 at 20:25
  • Thanks for pointing out there is no other way apart from restructuring my data. (I don't want to put the team names under user either, so I have to get the team IDs first then look for the teams). I understand it all happens asynchronously so the requests wouldn't queue up. I managed to pull the data, but just feeling there must be a better way (due to my unfamiliarity of NoSQL database queries). Also, I think this is a genuine question in lots of Firebase lovers' head, so please note that I asked the question with the intention to support the Firebase community. – Max Mar 27 '16 at 20:54
1

var data = { "users": { "u00001": { "name": "Andy", "teams": { "t001": true, "t003": true } }, }, "teams": { "t001": { "name": "Alpha Team" }, "t002": { "name": "Beta Team" }, "t003": { "name": "Gamma Team" } } }

function getNames(data, user) {
    var res = [];
    var teams = [];
    Object.keys(data.users).forEach(k => {
        if (data.users[k].name == user) {
            Object.keys(data.users[k].teams).forEach(t => teams.push(t))
        }
    });
    Object.keys(data.teams).forEach(t => {
        if (teams.indexOf(t) > -1) {
            res.push(data.teams[t].name);
        }
    });
    return res;
}

document.write(JSON.stringify(getNames(data, "Andy")));
isvforall
  • 8,768
  • 6
  • 35
  • 50
  • That definitely does apply for JSON. In this case the question also related to Firebase, which cloud-hosts the JSON. While you can download the entire JSON and do the filtering client-side with your code, this will become unwieldy as the data size grows. Using Firebase Queries ensures the filtering happens on the server (if the proper index is defined), so doesn't have that potential performance problem. – Frank van Puffelen Mar 27 '16 at 19:00
  • Btw: nice to see a runnable snippet. It's one of the things I miss when answering Firebase questions, since the database is not accessible within snippets. :-/ – Frank van Puffelen Mar 27 '16 at 19:01
  • @FrankvanPuffelen Firebase is nice but I am not familiar tightly with it yet, thanks for pointing me :) – isvforall Mar 27 '16 at 19:10