【问题标题】:How to efficiently query from Firebase Realtime Database using query or specific path如何使用查询或特定路径从 Firebase 实时数据库中高效查询
【发布时间】:2019-12-04 06:42:17
【问题描述】:

我们很少在 Firebase 实时数据库上进行属性修改(“价格”),其结构如下:

../currencies/<currency>/value/
      "price":343

每个登录的玩家只会听到一种特定的货币。我们的客户将根据玩家偏好选择正确的货币路径。

所以如果玩家设置为货币美元,firebase 客户端将监听此路径

../currencies/USD/value/
      "price":343

这些货币的价格很少更改
由于这种结构,我们的服务器端需要在数据发生变化时将数据修改和非规范化到所有货币(我们可以有数十种货币) 因此,我们在叶子中添加了更多相同在所有货币中

的属性

我觉得这有点像:

../currencies/USD/value/
          "price":343
          "currency-source":"fx" . //this property will be copied to all 

currencies vals 因为客户端只监听一个路径并且它也需要这些数据

如果在路径上维护它,也许我们可以使用一些查询,每个客户端都可以根据属性名称选择它的货币?

类似的东西:

../currencies/value/
          "USD_price":343
          "EUR_price":343
      ...

关于设计的想法?如果听起来更好,如何使用 Firebase 实时数据库查询来实现?

【问题讨论】:

  • 这似乎确实完全可行。与../currencies/&lt;currency&gt;/value 相比,您在收听../currencies/value/&lt;currency&gt;_price 节点时遇到任何困难吗? “如何使用 Firebase 数据库查询来实现”-> 您正在使用哪些 SDK(JS、Android、iOS)?
  • @RenaudTarnec 我们没有困难,我只是认为它复杂化了我们的 firebase 树模型而没有真正的价值。我们使用 JS SDK
  • “它使我们的 firebase 树模型复杂化,但没有真正的价值”-> 哪种方法使它复杂化?收听 ../currencies/value/_price 节点还是收听 ../currencies//value one?你到底在问什么?最好的方法是什么?
  • @RenaudTarnec ./currencies//值一? -> 让事情变得复杂(正如我在问题中详述的那样),因为我们复制了所有属性。而且我不知道如何在客户端使用 ./currencies/value/_price 方法,因此他只会使用玩家选择的货币。如果你能通过回答这个问题给我指路,我会很高兴
  • 您在前端使用哪种语言? IE。您使用的是哪个 Firebase 客户端 SDK?

标签: firebase firebase-realtime-database


【解决方案1】:

我不知道您在应用中使用哪种语言(哪种客户端 SDK),但这里有一个使用 JavaScript SDK 的解决方案。

假设你有一个如下的 Relatime 数据库结构

  "parentnode" : {
    "currencies" : {
      "EUR" : {
        "value" : {
          "price" : 201
        }
      },
      "USD" : {
        "value" : {
          "price" : 343
        }
      },
      "value" : {
        "EUR_price" : 201,
        "USD_price" : 343,
        "currency-source" : "fx"
      }
    }
  }

parentnode 下,您有一个currencies 节点对应于您问题中的示例

如果你想听/currencies/&lt;currency&gt;/value,你可以这样做:

  var db = firebase.database();

  var currency = 'EUR';

  var ref = db.ref().child('parentnode/currencies/' + currency);
  ref.on('value', function(snapshot) {
    var data = snapshot.val();
    console.log(data);
  });

如果您想收听/currencies/value/&lt;currency&gt;_price 并获取pricecurrency-source 值,您可以执行以下操作:

  var db = firebase.database();

  var currency = 'EUR';

  var ref = db.ref().child('parentnode/currencies/value');
  ref.on('value', function(snapshot) {
    var data = snapshot.val();
    var price = data[currency + '_price'];
    var source = data['currency-source'];
    console.log(price);
    console.log(source);
  });

正如您在评论中提到的,第二种方法意味着“我们将下载/currencies/value/ 下的所有数据叶”。

我可以想到另外两种可能的方法。选择其中一个实际上取决于您的功能要求,即您在前端如何处理这些值。

1/设置两个监听器

思路是为'parentnode/currencies/value/' + currency + '_price'设置一个监听器,为'parentnode/currencies/value/currency-source'设置一个监听器,如下:

  var currency = 'EUR';

  var ref2 = db
    .ref()
    .child('parentnode/currencies/value/' + currency + '_price');
  ref2.on('value', function(snapshot) {
    var data = snapshot.val();
    console.log(data);
  });

  var ref3 = db.ref().child('parentnode/currencies/value/currency-source');
  ref3.on('value', function(snapshot) {
    var data = snapshot.val();
    console.log(data);
  });

2/在监听器内查询currency-source

使用第二种方法,在'parentnode/currencies/value/' + currency + '_price' 的监听器中,我们使用once() 方法查询数据库以获得currency-source 的值:

  var ref4 = db
    .ref()
    .child('parentnode/currencies/value/' + currency + '_price');
  ref4.on('value', function(snapshot) {
    var data = snapshot.val();
    console.log(data);
    db.ref()
      .child('parentnode/currencies/value/currency-source')
      .once('value')
      .then(function(dataSnapshot) {
        console.log(dataSnapshot.val());
      });
  });

请注意,如果您不需要设置侦听器,即您只想获取一次数据(例如,通过从按钮触发获取,或在页面加载时等),您应该只使用once() 方法,然后您可以将两个调用链接如下:

  var currency = 'EUR';
  var ref5 = db.ref().child('parentnode/currencies/value/' + currency + '_price');
  var ref6 = db.ref().child('parentnode/currencies/value/currency-source');

  ref5
    .once('value')
    .then(function(dataSnapshot) {
      console.log(dataSnapshot.val());
      return ref6.once('value');
    })
    .then(function(dataSnapshot) {
      console.log(dataSnapshot.val());
    });

【讨论】:

  • 感谢您的回复。第二种方法是可行的。但这意味着我们将下载 /currencies/value/ 下的所有数据叶,因为 var price = data[currency + '_price'] 将在客户端本地工作。我认为有一种方法可以专门从 firebase 查询该键
  • 确实如此。昨天写完答案后,我真的想到了 :-) 我在答案中添加了可能的方法。
  • @rayman 实际上请注意,在我最初的回答中,我将once() 方法与on() 一个....需要使用on() 方法(我已经修改了答案)。如果您只想听一次(例如,通过从按钮触发提取,或在页面加载时等),您应该使用 once() 方法。
  • @rayman 嗨,您有机会查看更新吗?
  • 是的,在您的所有示例中,您下载所有叶子并进行本地操作。我想知道我是否可以利用 firebase 查询仅下载玩家需要的货币价格而不下载 all.currencies。因为我们可以轻松获得一百种货币。谢谢
猜你喜欢
  • 1970-01-01
  • 2022-06-10
  • 1970-01-01
  • 2019-08-07
  • 1970-01-01
  • 1970-01-01
  • 2019-07-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多