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



我们在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/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下,您有一个与问题中的示例相对应的currencies节点。

如果你想听/currencies/<currency>/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/<currency>_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());
});

最新更新