【问题标题】:Retrieving child record when parent key is unknown in Firebase当 Firebase 中的父键未知时检索子记录
【发布时间】:2017-05-24 02:10:55
【问题描述】:

我有这样的数据:

"customers": {
    "aHh4OTQ2NTlAa2xvYXAuY29t": {
        "customerId": "xxx",
        "name": "yyy",
        "subscription": "zzz"
    }
}

我需要通过 customerId 检索客户。由于路径限制,父键只是 B64 编码的邮件地址。通常我通过这个电子邮件地址查询数据,但有几次我只知道 customerId。我试过这个:

getCustomersRef()
   .orderByChild('customerId')
   .equalTo(customerId)
   .limitToFirst(1)
   .once('child_added', cb);

如果客户确实存在,这很有效。在相反的情况下,永远不会调用回调。

我尝试了value 事件,该事件有效,但这给了我以编码电子邮件地址开头的整个树,因此我无法访问内部的实际数据。或者我可以吗?

我找到了这个答案Test if a data exist in Firebase,但这再次假设你我知道所有路径元素。

getCustomersRef().once('value', (snapshot) => {
    snapshot.hasChild(`customerId/${customerId}`);
});

我还能在这里做什么?

更新

我想我找到了解决方案,但感觉不对。

let found = null;
snapshot.forEach((childSnapshot) => {
    found = childSnapshot.val();
});
return found;

【问题讨论】:

  • 另外this的回答可能对你有帮助
  • 你能澄清一下这个问题吗?它声明您要“在父键未知时检索子记录”。这就是 firebase 查询的作用——它“查看”一组节点以查看其中是否有任何一个与您指定的数据匹配的子节点——不需要指定父节点,只需指定作为父节点的节点包含您要查找的子节点的节点。

标签: javascript firebase


【解决方案1】:

旧的;误解了问题:

如果你知道“endcodedB64Email”,就是这样。:

var endcodedB64Email = B64_encoded_mail_address;

firebase.database().ref(`customers/${endcodedB64Email}`).once("value").then(snapshot => {
       // this is getting your customerId/uid. Remember to set your rules up for your database for security! Check out tutorials on YouTube/Firebase's channel.
       var uid = snapshot.val().customerId;
       console.log(uid) // would return 'xxx' from looking at your database

// you want to check with '.hasChild()'? If you type in e.g. 'snapshot.hasChild(`customerId`)' then this would return true, because 'customerId' exists in your database if I am not wrong ...
});

更新(更正):

我们必须至少知道一把钥匙。所以如果你在某些情况下 只知道customer-uid-key,那么我会这样做。:

// this is the customer-uid-key that is know. 
var uid = firebase.auth().currentUser.uid; // this fetches the user-id, referring to the current user logged in with the firebase-login-function
// this is the "B64EmailKey" that we will find if there is a match in the firebase-database
var B64EmailUserKey = undefined;

// "take a picture" of alle the values under the key "customers" in the Firebase database-JSON-object
firebase.database().ref("customers").once("value").then(snapshot => {
     // this counter-variable is used to know when the last key in the "customers"-object is passed
     var i = 0;
     // run a loop on all values under "customers". "B64EmailKey" is a parameter. This parameter stores data; in this case the value for the current "snapshot"-value getting caught
     snapshot.forEach(B64EmailKey => {
          // increase the counter by 1 every time a new key is run
          i++;
          // this variable defines the value (an object in this case)
          var B64EmailKey_value = B64EmailKey.val();
          // if there is a match for "customerId" under any of the "B64EmailKey"-keys, then we have found the corresponding correct email linked to that uid
          if (B64EmailKey_value.customerId === uid) {
               // save the "B64EmailKey"-value/key and quit the function
               B64EmailUserKey = B64EmailKey_value.customerId;

               return B64UserKeyAction(B64EmailUserKey)
          }

          // if no linked "B64EmailUserKey" was found to the "uid"
          if (i === Object.keys(snapshot).length) {
               // the last key (B64EmailKey) under "customers" was returned. e.g. no "B64EmailUserKey" linkage to the "uid" was found
               return console.log("Could not find an email linked to your account.")
          }
     });
});

 // run your corresponding actions here
 function B64UserKeyAction (emailEncrypted) {
      return console.log(`The email-key for user: ${auth.currentUser.uid} is ${emailEncrypted}`)
 }

我建议将它放在一个函数或类中,以便您可以轻松调用它并以有组织的方式重用代码。

我还想补充一点,必须定义您的 firebase 规则以确保一切安全。如果必须计算敏感数据(例如价格),请在 Firebase 的服务器端执行此操作!使用云函数。这是 Firebase 2017 的新功能。

【讨论】:

  • 这是一个有点老的问题,我不记得我是如何解决的,但正如我上面所说的“但有几次我只知道 customerId”。您的解决方案期望 endcodedB64Email 是已知的,但事实并非如此。
  • 你好。对于那个很抱歉。如果您只知道“customerId”,我现在已经更新了如何获得正确的“endcodedB64Email”的答案。告诉我这是不是你的想法。
  • 谢谢,但这必须有可怕的内存占用,基本上加载所有客户(直到找到正确的客户)。我想最后最好的方法是使用 customeri->email 单独查找地图。
  • 是的,肯定会占用更多内存。 Firebase 鼓励对数据库中分配的数据进行非规范化处理。使用您提到的单独查找 customerId => email 将是最好的!简单的代码,例如firebase.database().ref("users/" + auth.currentUser.uid).once("value").then(snap => {var email = snap.val().email});
  • 我确实认为如果必须这样做的话,这样做是可以的。如果我没记错的话,Firebase 就是为进行这种数据处理而构建的。不过,您的数据计划可能会增加。这个例子鼓励人们在需要时这样做。 firebase.docs
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多