Exploring various sub-arrays within Firebase

My title doesn't quite capture the issue I'm facing.

I've been delving into firebase and angularfire, learning how to work with data manipulation.

Everything was going smoothly until I encountered this peculiar array structure.

https://i.sstatic.net/kFdxh.png

This is my real-time Firebase database containing a history of sorts.

The main array represents the history itself, consisting of two sub-arrays (0 and 1) corresponding to user 0 and user 1's histories.

User 0's array includes their user ID (_ID) and two sub-arrays (0 and 1) indicating the levels they have completed.

Each sub-array records the number of times a level has been completed, the level's ID (_id), and additional sub-sub-arrays with data for each time the level was run.

Quite complex, isn't it? I hope you grasp the structure of my database. Admittedly, I may not have adopted the best practices in structuring my database.

My current challenge involves searching through these arrays for my AngularJS application.

For instance, I'm striving to create these variables:

$scope.history
$scope.userHistory
$scope.currentLevelUserHistory
$scope.lastRunCurrentLevelUserHistory

I've successfully retrieved the first two variables but can't seem to understand why the latter ones are failing.

Fetching history is simple; I just use this function in my factory:

getHistoriques : function () {
    return historiques;
}

Where "historiques" points to:

var ref = firebase.database().ref().child("historiques");
var historiques = $firebaseArray(ref);

Acquiring userHistory posed more of a challenge.

I devised this search function:

function search(key, array){
    console.log("Searching array with the key: " + key);
    for (var i=0; i < array.length; i++) {
        if (array[i]._id === key) {

            console.log(array[i]);
            return array[i];

        }
        else {

        }
    }
}

And the result is an object like this:

https://i.sstatic.net/yAJMG.png

However, progressing to the next step—currentLevelUserHistory—proved elusive. Despite trying ten different methods, I couldn't get it to work.

My final attempt involved injecting the output from the previous object back into the search function by adding the level ID.

Unfortunately, all I received was "undefined."

I experimented with various approaches, including adding [0] to my object, among other modifications. Yet, I remain puzzled as to why nothing seems to work. To me, the array and its sub-array appear unchanged.

Why is it failing? Could it be that the function's output is altering my array?

I realize my query is lengthy. Many thanks to those who took the time to read through it.

Thank you kindly.

First EDIT:

users
    |
    - userId (according to firebase auth)
        |
        - name: ...
        |
        - surname: ...
        |
        - age: ...
        |
        - allowed levels:
                        |
                        - allowedLevel001: levelId
                        |
                        - allowedLevel002: levelId
                        |
                        - allowedLevel003: levelId
        -...

levelsData
    |
    - levelId
        |
        - level name: ...
        |
        - level description: ...
        |
        - first step
            |
            - step name: ...
            |
            - step desc: ...
            |
            - action needed: ...
            |
            - time: ...
        - second step
            |
            - step name: ...
            |
            - step desc: ...
            |
            - action needed: ...
            |
            - time: ...    
    |
        -...    

levelsRunData
    |
    - userId+levelId
        |
        - run001
            |
            -
            first step result:
                |
                - ...
            second step result:
                |
                - ...   
            |
            -...
        - run002
            |
            -
            first step result:
                |
                - ...
            second step result:
                |
                - ...   
            |
            -...    

Answer №1

In considering the structure of your database, I have a few suggestions that align with what I perceive to be your specific use case. While I acknowledge that my assumptions may be incorrect, there are a couple of key points to address:

  1. It's crucial to view the Firebase RTDB database as a map consisting of key/value pairs rather than an array. Although you can input an array into the db, it will generate a succession of key/value pairs starting at 0 and increasing by 1 (while your current setup somewhat follows this pattern, it could lead to complications).
  2. When envisioning your database for accommodating 100k users, consider the implications on storage and data retrieval rates. Neglecting these factors could result in sluggish performance and hefty bills from Google.

In my opinion, using unique keys rather than numerical identifiers like 0, 1, 2 is essential for long-term usability. Many databases leverage the user ID generated during authentication via Firebase for all user references, eliminating the need for an additional 'id' property stored against each user.

I'm uncertain about the content under sub-sub-arrays 0 and 1, but descending five levels deep, while feasible, isn't recommended in a NoSQL database.

To illustrate, I propose the following database structure (assuming historiques serves as the root and excludes extraneous user details such as name, age, etc.):

Two primary nodes named levelsCompleted and levelRunData would appear as follows...

levelsCompleted
    |
    - userId  
        |
        - levelId001 : levelRunCount       
        (number of digits in levelId varies based on available levels)
        |
        - levelId002 : levelRunCount     
        |
        -...
 
levelsRunData     
    |     
    - userId+levelIdnnn (combine both IDs)         
        |        
        - run001             
            |               
            - run data (content unknown)          
        (number of digits in run adapts to potential runs)            
        |             
        - run002                
            |                   
            - run data                 
        |           
        - run003              
            |                 
            - run data            
        |              
        -...      

This configuration facilitates straightforward data retrieval according to the user's ID and relevant level ID. Hopefully, this offers clarity.

Updated Structure Following Your Initial Edit:

Please find below the suggested structure, now utilizing actual (proposed) property names. For reference, the designated record keys for each node are provided:

Node            Key Format                                   Name in Structure
----            ---------------------                        -----------------
users           <28 character user id from firebase_auth>    userId
levelsData      <'level'nnn eg. level001, level002>          levelId
levelsRunData   <userId + levelId + 'run'nnn>                N/a

We can delve deeper into this structure in our discussion.

Database Layout:

users
    |
    - userId (based on firebase auth)
        |
        - name : ...
        |
        - surname : ...
        |
        - age : ...
        |
        - allwdLvls
            |
            - level001 : levelRunCount
            |...
    
levelsData
    |
    - level001
        |
        - levelName : ...
        |
        - levelDesc : ...
        |
        - step001
            |
            - stepName : ...
            |
            - stepDesc : ...
            |
            - actionNeeded : ...
            |
            - time : ...
         -...    
    
levelsRunData
    |
    - <userId>+<levelId>+run001
        |
        - step001
            |
            - ...
            |- ...   
        |
        - step002
            |
            - ...
            |- ....   
        |
        -..
    |
    -....

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Customize the yellow background color of Safari's autofill feature by following these simple

When I open this image in Safari, this is what I see: https://i.stack.imgur.com/KbyGP.png However, this is the code I have: https://i.stack.imgur.com/4wEf0.png References: How to Remove WebKit's Banana-Yellow Autofill Background Remove forced ye ...

Implementing Asynchronous Rendering in React Router 4

I've been working with React Router 4 and trying to implement Redirect(Auth) following a guide. However, I'm facing an issue with rendering based on the promise returned by an AJAX call. It seems like my rendering logic inside the promise is not ...

Can you explain the function of a digest attribute?

As a beginner in the world of NextJS, I am currently working on getting my first project ready for production. However, I encountered the following error: Application error: a client-side exception has occurred (see the browser console for more information ...

Integrating a conditional statement into the existing for loop code to conceal the covers

My goal is to hide the covers after they are clicked using an if statement within the for loop code. I believe this is where it should be placed. Trying to prevent this action from happening. https://i.sstatic.net/eLSto.png I made an attempt at achievin ...

Cannot populate Kendo Menu with images due to dataSource imageUrl not recognizing the content

I have integrated Kendo controls into my application, specifically a Menu control with a datasource in my controller. Currently, I am passing the relative path of URL for imageUrl. However, as the application has grown, there are multiple calls being made ...

Flawless Incorporation with RESTful API

While there are countless tutorials online demonstrating how to utilize ng-repeat with in-memory data, my situation involves a lengthy table with infinite scroll that retrieves data through requests to a REST API (scroll down - fetch data, repeat). This me ...

Tips for hiding a sidebar by clicking away from it in JavaScript

My angular application for small devices has a working sidebar toggling feature, but I want the sidebar to close or hide when clicking anywhere on the page (i.e body). .component.html <nav class="sidebar sidebar-offcanvas active" id="sid ...

Having trouble getting the Random Function to function correctly in Discord.js

I'm working on a piece of code that generates a random value to select two different values from two separate arrays. Every time I run it, however, the result seems to be the same and not truly random. I'm not sure where I went wrong with this. I ...

Incorporate the module into both the parent and child class

In my coding project, I have a situation where both a parent class and a child class are importing the same lodash library. This raises the question: will the final bundled JavaScript file contain duplicate lodash code? //Parent Class import Component fro ...

Custom Email Template for Inviting Msgraph Users

I'm currently exploring the possibility of creating an email template for the MS Graph API. I am inviting users to join my Azure platform, but the default email they receive is not very visually appealing. public async sendUserInvite(body: {email: < ...

Send multiple input groups using Ajax POST requests

I need help setting up a form with 4 groups of checkboxes for refining search results. My goal is to send an array for each checkbox group that contains the IDs of the currently selected checkboxes. $.ajax({ url: "/stay_in_belfast/accommodation", t ...

Struggling to adjust the quantity of items in a basic shopping cart when adding multiples of the same item

Hello there! I'm currently working on a project where I need to increase the quantity of each item added to the cart if it's already in there. This is actually my first time posting, so any tips on asking better questions would be greatly appreci ...

Choose an element at random

I am trying to figure out how to select all div elements with the same class of "dot" under a parent div in JavaScript. Here is an example structure: <div id="dots"> <div class="dot"> . </div> <div class="dot"> . </div> ...

In jQuery, conditionally nest divs within another div based on a specific requirement

There is a container with multiple nested elements that need to be rearranged based on the value of their custom attribute. The goal is to reorder those elements at the end of the container if their 'data-keep-down' attribute is set to true, usin ...

Error: Phonegap displaying incomplete or corrupted image

Currently, my Android application is being developed with Phonegap. Users have the ability to take photos that are then stored in a mysql database (medium-blob column) using a simple INSERT INTO query without altering the data. These images are then sent s ...

The JSON data URLs in the `_next/data` directory of the NextJS app are returning a 404 error, however, when accessed directly in the

I am facing an issue with my Next.js (v13) app hosted on a self-hosted Kubernetes cluster. The AJAX JSON data calls from the _data directory are showing as 404 errors, even though when I directly visit the URLs in my browser, they load fine. I'm perp ...

"Utilize Node.js to generate a nested array structure with groupings

Here is an array data that I have: [ { tempId: 1, nik: '11002', employeeName: 'Selly Amaliatama', basic_salary: 3500000, id_component: 'AD0128114156', componentName: 'Tunjangan Maka ...

jQuery fadeIn effect happening at rapid speed

I am currently working on integrating ajax with WordPress. After the ajax call is completed, I am successfully fading out a specific div slowly. However, when trying to fade in the new data using jQuery's fadeIn() method, I noticed that regardless of ...

Protecting String in PHP to Utilize in JavaScript

When I receive code through AJAX, I handle it as shown below: $verifiedSubject = addslashes(htmlentities($_REQUEST['subject'])); $verifiedBody = addslashes(htmlentities($_REQUEST['body'])); $verifiedAttachment1 = addslashes(htmlentitie ...

Is there an implicit transformation or action involved when the promise chain is resolved or rejected in $q?

Is there an intrinsic digest/apply included when the promise chain is resolved/rejected in $q? I recently switched from using $q to q in my code and it seems like a digest is no longer happening, leading to different outcomes. What could be causing this c ...