Javascript firebase数据库安全规则中的未指定索引警告

Javascript firebase数据库安全规则中的未指定索引警告,javascript,firebase-realtime-database,google-cloud-functions,firebase-security,Javascript,Firebase Realtime Database,Google Cloud Functions,Firebase Security,我制作了一个云函数来删除过期的警报消息,我的数据结构如下: Alerts |-{country1} |-{c1_state1} |-{key} |-msg: "bla bla" |-end: 1601251200000 |-{c1_state2} |-{key} |-msg: "bla bla" |-end: 1601251200000 |-{country2} |-{c2_st

我制作了一个云函数来删除过期的警报消息,我的数据结构如下:

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
variable)

[2020-09-29T02:04:28.585Z]@firebase/数据库:firebase警告:使用未指定的索引。您的数据将在客户端上下载和筛选。考虑添加“.Noxon”:“结束”在/Actudis/BR/RR到您的安全规则以获得更好的性能。< /强>

我已经搜索了很多关于在firebase数据库中设置规则的内容,但我无法将这些规则付诸实施。在我的数据库中,我在国家和州循环,这就是为什么我使用通配符(
$coutry
$state

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

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();
        });
      }
    });
  }));
  
});

那么,如何正确地设置规则,以提高我的查询的性能而不发出警告?

事实上,如果您的应用程序现在没有太多数据,您的查询将正常工作,甚至可能感觉不到性能问题,使用通配符可能会影响性能,而
索引可能会对您有所帮助,因为它不依赖于客户端对其进行筛选和执行

然而,正如Firebase Engineer对此问题的评论所阐明的,不幸的是,无法设置通配符索引。如本例所示,更改数据库的结构将有助于解决此问题,因为您可以以一种可以轻松使用索引并提高性能的方式对其进行建模


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

我通过在每个节点上添加“.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"]
        }
      }
    }
  }
}

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

谢谢你的回答!是否可以逐个添加规则?我在
国家
中循环,在每个节点上添加“.indexOn”:“end”没有问题。对我来说,这比改变我的应用程序的业务逻辑要容易。嗨@AlitonOliveira,不幸的是,你无法做到这一点。
indexOn
用于规则的最后一部分,然后,您将准确地索引所需的数据。我同意你的观点,但实际上,使用它会比更改逻辑更容易,不幸的是,它也不适用于通配符,所以你将无法以这种方式使用索引。如果您愿意,您可以向Google提出功能请求,以检查是否实现了此功能。
{
  /* 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"]
        }
      }
    }
  }
}