【问题标题】:Searching across sub-arrays in Firebase在 Firebase 中搜索子数组
【发布时间】:2020-07-11 05:14:35
【问题描述】:

我的标题不是很准确,但我无法说出我遇到的问题。

所以我正在学习如何使用 firebase 和 angularfire,并且我正在学习如何操作数据。

在我遇到这种类型的数组之前,一切都找到了。

这是我来自 Firebase 的实时数据库,它是一段历史记录。

主数组是它自己的历史,它由两个数组(0和1)组成,分别指用户0和用户1的历史。

在用户0的数组中,有他的用户ID(_ID),以及两个子数组(0和1),分别代表他所做的级别。

每个子数组都有关卡执行的次数、关卡的ID (_id),以及包含每次关卡运行数据的少数子子数组。

有点复杂!我希望你了解我的数据库。我同意我没有关于如何构建数据库的最佳实践。

我的问题是,我希望为我的 angularjs 应用搜索这种类型的数组。

例如,我正在尝试制作这些变量:

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

我设法获得了前两个变量,但我不明白为什么我不工作如何下一个。

获取历史很容易,我只是在我的工厂使用这个功能

getHistoriques : function () {
    return historiques;
}

“历史”指的是这个

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

获取 userHistory 有点棘手。

我创建了这个函数

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 {

        }
    }
}

输出就是这样的对象。

但要进入下一步:currentLevelUserHistory。这对我来说是不可能的。我尝试了 10 种不同的方法,但都无法正常工作。

我的最后一次尝试是在搜索功能中重新注入前一个对象的输出,以及级别 ID。

但我得到“未定义”。

我尝试了很多东西,比如向我的对象添加一些 [0],添加一堆东西。但我不知道为什么它不起作用。对我来说,数组和子数组总是一样的。

为什么它不起作用?这是因为函数的输出正在修改我的数组?

我知道我的问题很长。非常感谢所有有勇气阅读它的人。

非常感谢。

第一次编辑:

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 :
                |
                - ...   
            |
            -...    

【问题讨论】:

  • 并不是我在回答您的问题,而是请注意,当您阅读“历史”时,您正在阅读整个数据库。您已经拥有该数据集中的所有内容,因此您可以通过仅处理该数据集来填充您正在寻找的其他变量。但是,下载该数据集可能会非常庞大​​,而且在时间和金钱上非常昂贵。
  • 我正在学习,所以我对优化和安全性还不太了解。我知道下载整个历史记录并没有优化和安全,因为用户可以访问其他用户的历史记录(所以它很大),但对我来说这个项目是一个教训。除非完全完成、优化和安全,否则我不会使用其中的任何一个。你有什么建议只检索想要的数据?谢谢
  • 你希望这些变量持有什么,即。它们是针对单个指定用户还是所有用户? $scope.userHistory $scope.currentLevelUserHistory $scope.lastRunCurrentLevelUserHistory
  • 好吧,用户正在登录,他启动关卡脚本,脚本在整个数据库中找出他的数据所在的位置,并将其应用于这些变量。但只有他能看到它们。但是每个用户每次想要做一个关卡时都可以创建这些变量。我不知道我是不是很清楚。对不起^^

标签: javascript angularjs firebase firebase-realtime-database angularfire


【解决方案1】:

我想就您的数据库结构提出一些建议。它们基于我认为您的用例。当然,我可能完全错了。首先,几个 cmets:

  1. 您需要将 Firebase RTDB 数据库视为键/值对的映射,而不是数组。它确实允许您将数组发布到数据库,但它会从中创建一系列键/值对,键从 0 开始并以 1 递增(您在当前的结构中有点这样做,但我认为它可以导致其他问题)。
  2. 当您需要处理 10 万用户时,您需要考虑数据库应该是什么样子。存储量和数据下载量就变得非常重要,否则您的应用程序将停止运行,Google 会向您提供 1000 美元的账单。

恕我直言,您的用户需要通过一个像样的唯一密钥来识别,而不是 0、1、2。从长远来看,这会让您反胃,相信我。许多数据库结构使用用户通过 Firebase 身份验证对应用程序进行身份验证时创建的用户 ID - 您应该考虑将其用于数据库中对用户的所有引用。这消除了 id: 您针对每个用户存储的属性,因为它已经在密钥中。

我看不到您在子子数组 0 和 1 下有什么数据,但您已经下降了 5 个级别,虽然可行,但在 NoSQL 数据库中进行深度嵌套并不好。

所以,恕我直言,您的数据库可能如下所示(我假设 historiques 是 root 并且您不需要保留有关用户的任何其他详细信息,例如姓名、年龄等。如果您这样做了,那么您需要一个名为 users 的节点,以 userId 作为键。):

两个数据库节点称为levelsCompleted 和levelRunData。它们看起来像......

levelsCompleted
    |
    - userId
        |
        - levelId001 : levelRunCount
        (number of zeroes in levelId depends on how many possible levels there are)
        |
        - levelId002 : levelRunCount
        |
        -...

levelsRunData
    |
    - userId+levelIdnnn (concatenate the two ids)
        |
        - run001
            |
            - run data (don't know what is in here).
        (number of zeroes in run depends on how many possible runs there are)
        |
        - run002
            |
            - run data
        |
        - run003
            |
            - run data
        |
        -...

然后根据用户的 id 和级别 id 读取您需要的数据变得相当简单。 希望这是有道理的。

根据您的第一次编辑更新:

请参阅下面的建议结构。我现在使用实际(建议的)属性名称。此外,为清楚起见,以下是每个节点的建议记录键:

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

然后我们可以在聊天室讨论它。

数据库结构:

users
    |
    - userId (according to firebase auth)
        |
        - name : ...
        |
        - surname : ...
        |
        - age : ...
        |
        - allwdLvls
            |
            - level001 : levelRunCount
            |
            - level002 : levelRunCount
            |
            - level003 : levelRunCount
        -...

levelsData
    |
    - level001
        |
        - levelName : ...
        |
        - levelDesc : ...
        |
        - step001
            |
            - stepName : ...
            |
            - stepDesc : ...
            |
            - actionNeeded : ...
            |
            - time : ...
        - step002
            |
            - stepName : ...
            |
            - stepDesc : ...
            |
            - actionNeeded : ...
            |
            - time : ...    
    |
    - level002
        |
        - levelName : ...
        -... 
    -...

levelsRunData
    |
    - <userId>+<levelId>+run001
        |
        - step001
            |
            - ...
            |
            - ...
        |
        - step002
            |
            - ...
            |
            - ...
        |
        -...
    - <userId>+<levelId>+run002
        |
        - step001
            |
            - ...
            |
            - ...
        |
        - step002
            |
            - ...
            |
            - ...
        |
        -...
    |
    -...

【讨论】:

  • 非常感谢您的留言。我现在明白了更多的事情。我很感激。我试图根据您的建议安排我的数据库,我不知道如何做一个很长的回复,所以我编辑了我的问题并在底部添加了引用。我还有一些关于搜索和连接 id 的问题,但如果你能就我的数据库的新结构给我你的意见,那就太好了。 :)
  • 通过此房间的 SO 聊天回复:chat.stackoverflow.com/rooms/info/210871/…
  • 我发送了一条新消息。我不知道您是否在聊天中收到通知,所以我在这里告诉您。谢谢。
  • 已回复聊天。
猜你喜欢
  • 2018-06-05
  • 2017-03-10
  • 1970-01-01
  • 2021-04-09
  • 1970-01-01
  • 1970-01-01
  • 2017-03-21
  • 2017-05-09
相关资源
最近更新 更多