【问题标题】:Unspecified index warning in firebase database security rulesFirebase 数据库安全规则中的未指定索引警告
【发布时间】:2021-01-14 15:13:19
【问题描述】:

我已经做了一个删除过期警报消息的云功能,我的数据结构如下:

Alerts
|-{country1}
  |-{c1_state1}
    |-{key}
      |-msg: "bla bla"
      |-end: 1601251200000
  |-{c1_state2}
    |-{key}
      |-msg: "bla bla"
      |-end: 1601251200000

|-{country2}
  |-{c2_state1}
    |-{key}
      |-msg: "bla bla"
      |-end: 1601251200000
  |-{c2_state2}
    |-{key}
      |-msg: "bla bla"
      |-end: 1601251200000

查看日志消息,我注意到 for 循环中的每个查询都有很多警告(states 变量)。

[2020-09-29T02:04:28.585Z] @firebase/database: FIREBASE 警告:使用未指定的索引。您的数据将在客户端下载和过滤。考虑将 /Alerts/BR/RR 处的 ".indexOn": "end" 添加到您的安全规则中以获得更好的性能。

我已经搜索了很多关于在 firebase 数据库中设置规则的信息,但我无法让这些规则发挥作用。在我的数据库中,我在国家和州中循环,这就是我使用通配符的原因($coutry$state

{
  /* Visit https://firebase.google.com/docs/database/security to learn more about security rules. */
  "rules": {
    ".read": "auth != null",
    ".write": "auth != null",
    "Alerts": {
      "$country": {
        "Sstate": {
          ".indexOn": ["end"]
        }
      }
    }
  }
}

我的功能正常工作,数据按预期删除,但警告不断出现。

exports.closeAnnouncementsBRTZ3 = functions.pubsub
.schedule('10 0 * * *')
.timeZone('America/Sao_Paulo') // Users can choose timezone - default is America/Los_Angeles
.onRun((context) => {

  const expireTime = 1601251200000;

  const ref = admin.database().ref().child('Alerts').child('BR');
  
  const states = ['AC', 'AM', 'MS', 'MT', 'RO', 'RR'];
  
  return Promise.all(states.map(async (state) => {
    return await ref.child(state).orderByChild('end').endAt(expireTime).once('value', (dataSnapshot) => {
      console.log('await dataSnapshot: ', state);
      if (dataSnapshot.val() !== null) {
        dataSnapshot.forEach(childSnapshot => {
          console.log('child to be removed: ', childSnapshot.key);
          childSnapshot.ref.remove();
        });
      }
    });
  }));
  
});

那么,如何正确设置规则以提高查询性能且不会出现警告?

【问题讨论】:

    标签: javascript firebase-realtime-database google-cloud-functions firebase-security


    【解决方案1】:

    我已经通过在每个节点上添加 ".indexOn": "end" 来解决它,即使有些节点还不存在。

    {
      /* Visit https://firebase.google.com/docs/database/security to learn more about security rules. */
      "rules": {
        ".read": "auth != null",
        ".write": "auth != null",
        "Alerts": {
          "BR": {
            "AC": {
              ".indexOn": ["end"]
            },
            "AM": {
              ".indexOn": ["end"]
            },
            "MS": {
              ".indexOn": ["end"]
            },
            "MT": {
              ".indexOn": ["end"]
            },
            "RO": {
              ".indexOn": ["end"]
            },
            "RR": {
              ".indexOn": ["end"]
            }
          }
        }
      }
    }
    

    这不是一种方便的解决方法,因为我们必须为项目中每个可能的节点设置规则。但是一旦完成……就完成了!

    【讨论】:

      【解决方案2】:

      确实,如果您的应用程序现在没有太多数据,您的查询将起作用,您甚至可能感觉不到性能问题,但是,确实,使用通配符可能会影响您的性能,index 可能会有所帮助你,因为它不依赖于它在客户端被过滤和执行。

      但是,正如 Firebase 工程师提供的这个问题的评论 here 中所阐明的那样,很遗憾,无法设置通配符索引。正如本案例here 中所指出的,更改数据库的结构将帮助您解决此问题,因为您可以轻松地使用索引并提高性能来对其进行建模。

      总而言之,您需要更改数据库结构以提高性能,因为索引不能像您那样使用通配符。

      【讨论】:

      • 感谢您的回答!是否可以一一添加规则?我在countrystates 中循环,我认为在每个节点上添加 ".indexOn": "end" 没有问题。对我来说,这比更改应用程序的业务逻辑要容易。
      • 嗨@AlitonOliveira,很遗憾,您将无法做到这一点。 indexOn 用于规则的最后一部分,在那里,您将准确索引您想要的数据。我同意你的观点,虽然确实,使用它比改变你的逻辑更容易,不幸的是,它也不适用于通配符,所以你将无法以这种方式使用索引。如果您愿意,您可以向 Google 提出功能请求以检查是否实施此 here
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-10-08
      • 1970-01-01
      • 2016-09-16
      • 1970-01-01
      • 2019-04-19
      • 2021-12-31
      相关资源
      最近更新 更多