Amit
Amit

Reputation: 6304

Firebase how to index this data to be fetched?

I have a DB with users and items.

Every user has languages, which is an array of languages, for example ['en', 'ar']

Every item has language, which is a string, for example 'en'.

How can I index my items, such that I can get a list of the last X items in an array of languages? (i.e - latest 5 items who are either 'en' or 'ar')

For a single language the solution is simple - have an index that has the language key, and array of item keys ordered by whatever.

Upvotes: 0

Views: 553

Answers (1)

Alex Mamo
Alex Mamo

Reputation: 138834

Please note that the Firebase official documentation recommends against using arrays. IMHO, the main problem in your project is that you trying to use an array, which is an anti-pattern when it comes to Firebase. Beside that, one of the many reasons Firebase recommends against using arrays is that it makes the security rules impossible to write. Because a Firebase database is structured as pairs of key and values, the best option is to use a Map.

To achieve what you want, i recomand you using a database structure which looks like this:

Firebase-root
    |
    --- users
    |     |
    |     --- UID1
    |     |    |
    |     |    --- languages
    |     |            |
    |     |            --- languageId1: true
    |     |            |
    |     |            --- languageId2: true
    |     |
    |     --- UID2
    |          |
    |          --- languages
    |                  |
    |                  --- languageId3: true
    |                  |
    |                  --- languageId4: true
    |
    --- languages
    |      |
    |      --- languageId1
    |      |      |
    |      |      --- languageName: "en"
    |      |      |
    |      |      --- items
    |      |           |
    |      |           --- itemId1: true
    |      |
    |      --- languageId2: "ar"
    |      |      |
    |      |      --- languageName: "ar"
    |      |      |
    |      |      --- items
    |      |           |
    |      |           --- itemId2: true
    |
    --- item
         |
         --- itemId1
         |     |
         |     --- title: "ItemTitleEn"
         |     |
         |     --- en: true
         |
         --- itemId2
               |
               --- title: "ItemTitleAr"
               |
               --- ar: true

Now, with this database structure you can achieve everything you want. For example, you can query your database to display all languages from you database. You can also display all the languages of a single user.

If you want to query your database for the last x item which have the language set to en, you just need to put a listener on the items node and create a query using functions like: orderByChild(), equalsTo() and limitToLast(). Such a query should look like this:

query = rootRef.child("items")
    .orderByChild("en")
    .equalsTo(true)
    .limitToLast(5)
    .addListener(/* ... */)

EDIT: Unfortunately Firebase does not allow multiple conditions in a query. So in Firebase there is no where clause that sounds like this: WHERE language = "en" AND language = "ar". So to solve this, you need to put a listener on the other node, on languages node.

The flow is as follows:

yourRef = rootRef.child("languages"); //only one listener
yourRef.addListener(
    1. Create a list
    2. get items from dataSnapshot.child("languageId1").child("items").getChildren()
    3. add **en** items to the list
    4. get items from dataSnapshot.child("languageId2").child("items").getChildren()
    5. add **ar** items to the list
    6. display the list that contains data from both languages
)

Hope it helps.

Upvotes: 1

Related Questions