2

If I have a database like

users: {
  user1: { 
    name:'qwert', 
    id: 123,
    num: 9999 
  },
  user2: { 
    name:'zxcvb', 
    id: 456,
    num: 8888 
  }
}

How can I read only name of all the users?

My expected result:

{
  user1:{
    name:'qwert'
  }, 
  user2:{
    name:'zxcvb'
  }
}

If I use this in JavaScript:

ref('users').once('value').then((snap)=>{console.log(snap.val())})

I get all the users with that all their data (but I only want name of each)

What changes should I make in my query to get the expected result?

Any suggestions would be highly appreciated and really helpful. I tried searching through the docs but didn't get what I was trying to look for.

My ultimate aim is to cut down the costs of reading unnecessary data.

3 Answers3

3

There is no way to select only the names from your current data model, Firebase always retrieves full nodes. So you will either have to do what Peter answered, reading all data but extracting the user name client side, or you will have to modify you data model to allow the use-case.

The latter is quite simple. If you want to load a list of user names, you should store a list of user names in the database:

users: {
  user1: { 
    name:'qwert', 
    id: 123,
    num: 9999 
  },
  user2: { 
    name:'zxcvb', 
    id: 456,
    num: 8888 
  }
},
usernames: {
  user1: 'qwert', 
  user2: 'zxcvb'
}

With this structure, it is trivial to read only the names.

Also see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Yes, you are right this is faster, but what if he wants to only read the "age" and only read the "id", then only read the "num".. Then he has to do each one alone in that case :p – Peter Haddad Jun 28 '18 at 15:47
  • 1
    Neither of those use-cases is as common as wanting a list of user names. For example, a list of user ages without user identification seems pretty useless. Now a list of all ages in the database, so that you then see the users with that age, sounds like a more plausible use-case and would require a different type of data structure again. What all of these have in common is that they duplicate data when it's written, to reduce the time it takes to query/bandwidth it takes to load when reading the data for a use-case. – Frank van Puffelen Jun 28 '18 at 16:11
1

To retrieve only the names of the users, then try the following:

firebase.database().ref().child("users").on("value", function (snapshot) {
  snapshot.forEach(function(childSnapshot) {
   var name=childSnapshot.val().name;
  });
});

Here the snapshot is users, then you iterate inside user1 and user2 to be able to access the names of these users and retrieve them.

Peter Haddad
  • 78,874
  • 25
  • 140
  • 134
  • 5
    You might want to highlight that this *retrieves* all data, but only *displays* the user names. – Frank van Puffelen Jun 28 '18 at 13:52
  • Well yes it will retrieve everything under `users` and displays the name since that is what was specified in the answer. Why is there another way? – Peter Haddad Jun 28 '18 at 13:55
  • Since OP asked "How can I read only name of all the users?", I'd be explicit about this reading more than just their names. See my answer for alternative approach, which reduces the amount of data that needs to be read by duplicating some of the data in an additional list. – Frank van Puffelen Jun 28 '18 at 13:57
  • 1
    Hi Peter! Although this answers my question partially, my ultimate aim is to reduce the data downloaded/uploaded from/to database. As I use the blaze plan, I want to make sure I cut out the unnecessary charges for downloading unnecessary data. @FrankvanPuffelen approach is what I have been following(and hopefully that's the best suitable). It lowers the amount of data being read over several times at the cost of writing it only once. –  Jun 28 '18 at 20:20
  • @IshanNaktode yes it's fine, but do you even know how to retrieve the names when you have this database `usernames: { user1: 'qwert', user2: 'zxcvb' }`? – Peter Haddad Jun 29 '18 at 05:33
  • @PeterHaddad I agree the structure lacks semantics, it should have been something like this: `usernames: { user1: { name: 'qwert' } }` Yes that basically is the same as **users**. Only the amount of data is less. That means additional writing, but when you read it would be obviously quicker. Thanks. –  Jul 03 '18 at 16:27
  • yup that is what I mean, that you need an attribute example "name" to be able to retrieve easily @IshanNaktode – Peter Haddad Jul 03 '18 at 16:29
0

I guess I'm late but after some extensive research, there is a way in which we can fetch specific fields from firestore. We can use the select keyword, you're query would be somthing like (I'm using a collection for a generalized approach):

const result = await firebase.database().collection('users').select('name').get();

Where we can access the result.docs to further retrieved the returned filtered result. Thanks!