PeeJee
PeeJee

Reputation: 696

Firebase orderByChild not returning an array

I'm trying to retrieve some data from my firebase database, but I'm stuck on one little problem.

This is my object:

{
  "icons": [
    {
      "type": "animal",
      "url": "https://firebasestorage.googleapis.com/v0/b/kowloon-25cca.appspot.com/o/icons%2Fnavigation%2Fanimals%2Fdog.png?alt=media&token=08e0e162-8a72-467b-acdd-4085ac35e9c5",
      "alt": "Dog icon."
    },
    {
      "type": "animal",
      "url": "https://firebasestorage.googleapis.com/v0/b/kowloon-25cca.appspot.com/o/icons%2Fnavigation%2Fanimals%2Fcat.png?alt=media&token=1e58598b-00dc-4684-a349-00e1f9161256",
      "alt": "Cat icon."
    },
    {
      "type": "animal",
      "url": "https://firebasestorage.googleapis.com/v0/b/kowloon-25cca.appspot.com/o/icons%2Fnavigation%2Fanimals%2Ffish.png?alt=media&token=614d7867-2d43-48b7-a3ad-2680de6c7e10",
      "alt": "Fish icon."
    },
    {
      "type": "animal",
      "url": "https://firebasestorage.googleapis.com/v0/b/kowloon-25cca.appspot.com/o/icons%2Fnavigation%2Fanimals%2Fbird.png?alt=media&token=a7020145-1a30-4728-a9bb-144716213e55",
      "alt": "Bird icon."
    },
    {
      "type": "animal",
      "url": "https://firebasestorage.googleapis.com/v0/b/kowloon-25cca.appspot.com/o/icons%2Fnavigation%2Fanimals%2Fhamster.png?alt=media&token=2ee69ccc-ef55-4219-850f-7c0c384aafb6",
      "alt": "Hamster icon."
    },
    {
      "type": "general",
      "url": "https://firebasestorage.googleapis.com/v0/b/kowloon-25cca.appspot.com/o/icons%2Fnavigation%2Fgeneral%2F0_hamburger.png?alt=media&token=96c8779f-e261-448c-abce-41449b527f1f",
      "alt": "Burger icon."
    },
    {
      "type": "general",
      "url": "https://firebasestorage.googleapis.com/v0/b/kowloon-25cca.appspot.com/o/icons%2Fnavigation%2Fgeneral%2F1_search.png?alt=media&token=194afb95-fd57-4a48-acb0-63893c7111fa",
      "alt": "Search icon."
    },
    {
      "type": "general",
      "url": "https://firebasestorage.googleapis.com/v0/b/kowloon-25cca.appspot.com/o/icons%2Fnavigation%2Fgeneral%2F2_faq.png?alt=media&token=08f1e338-4e2b-4d72-a88f-4bbabf903da3",
      "alt": "Faq icon."
    },
    {
      "type": "general",
      "url": "https://firebasestorage.googleapis.com/v0/b/kowloon-25cca.appspot.com/o/icons%2Fnavigation%2Fgeneral%2F3_divider.png?alt=media&token=e7dddb6e-a241-4819-8a35-5facfaf45dab",
      "alt": "Divider icon."
    }
  ]
}

Now when I use this query to select some data I get the result I want (note the equalTo()):

  componentWillMount = () => {
    database.ref('icons').orderByChild('type').equalTo('animal').on('value', snap => {
      // this.setState({ icons: snap.val() });
      console.log(snap.val());
    })
  }

Result: Expected log

enter image description here

But now when I change the equalTo() field to 'general' - the type of the other icons - it's not returning an array.

  componentWillMount = () => {
    database.ref('icons').orderByChild('type').equalTo('general').on('value', snap => {
      // this.setState({ icons: snap.val() });
      console.log(snap.val());
    })
  }

Result: Wrong output

enter image description here

As you see, it's now returning an object instead of an array. Now my question: how can I fix this so that type 'general' also returns an array?

Thanks.

Upvotes: 0

Views: 624

Answers (2)

Reza Nasiri
Reza Nasiri

Reputation: 1435

based on the Firebase documents val() method can return different data types

Depending on the data in a DataSnapshot, the val() method may return a scalar type (string, number, or boolean), an array, or an object. It may also return null, indicating that the DataSnapshot is empty (contains no data).

if you need to iterate over the returned values, it is better to use forEach() method.

Upvotes: 0

Frank van Puffelen
Frank van Puffelen

Reputation: 599101

The Firebase Realtime Database doesn't store arrays. It instead stores them as regular JavaScript objects, which just happen to have sequential, numeric keys. So the data you store, is actually stored like this:

{
  "icons": {
    "0": { "type": "animal", "url": "...", "alt": "Dog icon." },
    "1": { "type": "animal", "url": "...", "alt": "Cat icon." },
    "2": { "type": "animal", "url": "...", "alt": "Dog icon." },
    "3": { "type": "animal", "url": "...", "alt": "Cat icon." },
    "4": { "type": "animal", "url": "...", "alt": "Dog icon." },
    ...
  }
}

So when you perform your query, you get a subset of these results. In your case it seems you get results 5 through 8. When the Firebase client gets a result that looks like an array, it converts it back to an array. But that requires for example that the index of the first result is 0, which it isn't in this case. So instead you get the raw result from the JSON.

To get it into an array, you should convert it yourself. That's quite simple, with something like:

database.ref('icons').orderByChild('type').equalTo('animal').on('value', snap => {
  let result = [];
  snap.forEach(child => {
    result.push(child.val());
  });
  console.log(result);
})

Also see:

Upvotes: 3

Related Questions