在嵌套的Firebase实时数据库结构中添加索引的正确方法

时间:2018-11-14 08:27:51

标签: node.js firebase firebase-realtime-database

by数据库的结构如下:

my-db
    |
    Users
        |
        CreatedAt: "SOME_VALUE"
        |
        Email: "SOME_EMAIL"
        |
        Mailboxes
                |
                445566
                    |
                    Address: "My address 1"
                    |
                    Status: Active
                |
                112233
                    |
                    Address: "My address 2"
                    |
                    Status: Active

我想做的是仅过滤具有特定ID的活动邮箱的用户。为此,我使用firebase cloud functions的方式如下:

db.ref('/Users')
    .orderByChild('mailboxes/' + mailboxId + '/status')
    .equalTo('Active')
    .once("value", function(snapshot){
      snapshot.forEach(function(childSnapshot){
        // GET SPECIFIC USER DATA FROM childSnapshot
      })
    })

到目前为止,它似乎运行良好,但是我在firebase函数日志中收到警告错误,提示:

  

@ firebase / database:防火墙警告:使用未指定的索引。您的   数据将在客户端上下载并过滤。考虑添加   / users中的“ .indexOn”:“ mailboxes / 445566 / status”到您的安全规则   以获得更好的性能。

我尝试在规则文件中添加索引:

{
  "rules": {
    ".read": true,
    ".write": true,
    "users": {
      "$userid": {
        "mailboxes": {
          "$mailboxid": {
            ".indexOn": ["status"]
            } 
        }
      }
    }
  }
}

但仍然没有成功。我现在想知道这里有什么不正确。

1 个答案:

答案 0 :(得分:1)

需要在运行查询的位置上定义索引。因此,由于您在/Users上运行查询,因此需要在其中定义索引。如错误消息所述:

{
  "rules": {
    ".read": true,
    ".write": true,
    "users": {
      ".indexOn": "mailboxes/445566/status"
    }
  }
}

但是您会立即注意到,这意味着每个UID都需要一个索引,这是不可行的。原因是Firebase数据库只能查询平面列表,不能查询多个级别。

您当前的数据结构使您可以有效地读取给定用户的所有邮箱。但是,它不能轻松地让您查找特定邮箱状态的所有用户。要允许后者,您将需要一个附加的数据结构,在其中存储邮箱列表(要查询的实体),邮箱状态(要过滤的条件)以及用户列表(想要的结果)

mailboxes: {
  "445566": {
    "Status": "Active",
    "user": "uid1"
  },
  "112233" {
    "Status": "Active",
    "user": "uid2"
  }
}

使用上述其他结构,您可以使用此索引:

"mailboxes": {
  ".indexOn": "Status"
}

接下来,您查询此/mailboxes以获取具有特定状态的所有邮箱,然后确定要显示的唯一用户。

另请参阅:

相关问题