如何使用查询或特定路径从Firebase实时数据库高效查询

如何使用查询或特定路径从Firebase实时数据库高效查询,firebase,firebase-realtime-database,Firebase,Firebase Realtime Database,我们很少对Firebase实时数据库进行财产修改(“价格”),其结构如下: ../currencies/<currency>/value/ "price":343 这些货币的价格很少变动 由于这种结构,当数据发生变化时,我们的服务器端需要对所有货币的数据进行修改和非规范化(我们可以有十种货币) 正因为如此,我们在leaf中添加了更多在所有货币上都相同的属性 我觉得这是多余的,比如: ../currencies/USD/value/ "price":3

我们很少对Firebase实时数据库进行财产修改(“价格”),其结构如下:

../currencies/<currency>/value/
      "price":343
这些货币的价格很少变动
由于这种结构,当数据发生变化时,我们的服务器端需要对所有货币的数据进行修改和非规范化(我们可以有十种货币) 正因为如此,我们在leaf中添加了更多在所有货币上都相同的属性

我觉得这是多余的,比如:

../currencies/USD/value/
          "price":343
          "currency-source":"fx" . //this property will be copied to all 
因为客户机只侦听一条路径,而且它也需要这些数据,所以使用VAL

相反,如果在路径上保存了这个,也许我们可以使用一些查询,每个客户都可以根据属性名称选择其货币

诸如此类:

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

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

我不知道您在应用程序中使用哪种语言(哪种客户端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
下有一个
currences
节点,该节点对应于您问题中的示例

如果您想收听
/currences//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);
  });
  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);
  });
  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);
  });
  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());
    });
如果您想收听
/currences/value/\u price
并获取
价格
货币源
值,请执行以下操作:

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

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

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

1/设置两个侦听器 其思想是为
'parentnode/currencies/value/'+currency+'\u price'
设置一个侦听器,并为
'parentnode/currencies/value/currency source'
设置一个侦听器,如下所示:

  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);
  });
  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);
  });
  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);
  });
  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());
    });
2/查询侦听器中的
货币源
值 使用第二种方法,在
'parentnode/currences/value/'+currency+'\u price'
的侦听器中,我们使用以下方法查询数据库以获取
货币源的值:

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

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

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

这似乎完全可行。与
。/currences//value
节点相比,您在收听
。/currences//value
节点时是否遇到任何困难?“Firebase数据库查询如何实现”->您正在使用哪些SDK(JS、Android、iOS)?@RenaudTarnec我们没有困难,我只是认为这会使Firebase树模型复杂化,而没有实际价值。我们使用JSSDK“它使我们的firebase树模型复杂化,而没有实际价值”->哪种方法使它复杂化?收听../Currences/value/_价格节点或收听../Currences//value one?你到底在问什么?最佳方法是什么?@RenaudTarnec./currences//value one?->使事情变得复杂(正如我在问题中详述的),因为我们复制了所有属性。我不知道如何在客户端使用./currences/value/_price方法,所以他只会选择玩家选择的货币。如果你能回答这个问题,告诉我你在前端使用哪种语言,我会很高兴的?例如,您使用的是哪种Firebase客户端SDK?谢谢您的回复。第二种方法是可行的。但这意味着我们将下载/currences/value/下的所有数据页,因为var price=data[currency+''u price']将在客户端本地工作。我认为有一种方法可以从firebaseYes中专门查询该密钥。在昨天写了答案之后,我真的想了想:-)我在答案中添加了一些可能的方法。@rayman实际上注意到,在我最初的答案中,我把
one()
方法和
on()
one方法混在了一起。。。。由于要设置侦听器,您需要使用
on()
方法(我已经修改了答案)。如果您只想听一次(例如,通过从按钮触发获取,或在页面加载等…),您应该使用
one()
方法。@rayman您好,您有机会看一下更新吗?是的。在所有示例中,您都下载了所有leaf,并进行本地操作。我想知道我是否可以利用firebase query只下载玩家需要的货币价格,而不下载所有的货币,因为我们可以轻松获得100种货币。谢谢