我现在花了16个小时的时间用javascript撕掉我的头发,所以我觉得是时候问别人了。
我有一个在android studio中制作的Android应用程序,它连接到一个看起来大致如下的firebase数据库:
nameOfDatabase
Places
Bar
B001
place_ID_ : "B001"
...
average_rating_ : 0
...
number_of_ratings_ : 0
...other bars
...other place types
Ratings
ratingID1
place_ID_ : "B001"
rating_ : 3
user_ID_ : 4315732985097
...other parameters
...other ratings
我想要做的只是更新rating_ID_的匹配place_ID_的地方的number_of_ratings_和average_ratings_,无论是通过修改现有值还是添加新评级。我的firebase函数节点模块的index.js代码如下所示:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.UpdateAverageRatings = functions.database.ref('/Ratings/{rating_uid}/rating_').onWrite(event => {
let place_ID_ = admin.database().ref('Ratings/' + String(event.params.rating_uid) + '/place_ID_').val();
console.log(place_ID_);
let place_type_ = 'BARs';
let place_ID_ = 'B001';
let avg_rating_ = 0;
let accumulated_rating_ = 0;
let number_of_ratings_ = 0;
//Object.keys(place_ID_.parent).forEach(function(key) {
// if (place_ID_.parent[key] == 'place_ID_'){
// accumulated_rating_ += place_ID_.parent[key].value();
// number_of_ratings_ += 1;
//}});
let place_change_ = admin.database().ref('Places/' + String(place_type_) + '/' +String(place_ID_));
place_change_.child('average_rating_').set(avg_rating_);
place_change_.child('number_of_ratings_').set(number_of_ratings_);
return 0;
});
在返回之前的最后两行中设置值可以正常工作,但是现在我只是将虚拟值设置为“0”。注释掉了分配正确值的想法供以后使用。
问题在于,无论我尝试什么,我似乎都无法读取数据库中的任何值,如'let place_ID_ ...'行和随后的控制台日志所示。 < / p>
我已经无数次阅读了文档(https://firebase.google.com/docs/functions/database-events)和stackexchange帖子,但我得到了
“TypeError:admin.database(...)。ref(...)。val不是函数”
在firebase控制台日志中,或者如果我删除val();
W {
u:
dh {
app:
FirebaseApp {
firebaseInternals_: [Object],
services_: [Object],
isDeleted_: false,
name_: '[DEFAULT]',
options_: [Object],
database: [Function: bound ],
INTERNAL: [Object] },
L:
Tb {
host: 'projectname.firebaseio.com',
domain: 'firebaseio.com',
Pc: true,
ne: 'projectname',
tg: false,
ef: '',
Za: 'projectname.firebaseio.com' },
Ua: Ff { qc: {} },
Sc: null,
ca: he { tb: [] },
td: 1,
Qa:
kh {
id: 0,
f: [Function],
nd: {},
'$': {},
pa: [],
Lc: 0,
Hc: [],
ma: false,
Ra: 1000,
qd: 300000,
Eb: [Function: bound ],
Gc: [Function: bound ],
se: [Function: bound ],
L: [Object],
xe: null,
Ab: null,
Ea: null,
mb: null,
Xc: [Object],
ae: false,
he: 0,
Rd: undefined,
sb: [Object],
Kb: true,
Ed: {},
kg: 0,
Oe: true,
je: null,
xc: null },
va:
kh {
id: 0,
f: [Function],
nd: {},
'$': {},
pa: [],
Lc: 0,
Hc: [],
ma: false,
Ra: 1000,
qd: 300000,
Eb: [Function: bound ],
Gc: [Function: bound ],
se: [Function: bound ],
L: [Object],
xe: null,
Ab: null,
Ea: null,
mb: null,
Xc: [Object],
ae: false,
he: 0,
Rd: undefined,
sb: [Object],
Kb: true,
Ed: {},
kg: 0,
Oe: true,
je: null,
xc: null },
qg: Df { qf: {}, Sc: [Object], va: [Object] },
jc: Vc { sd: '', Mc: null, A: [Object] },
fe: Nb { Hd: [Object] },
md: Dg { wa: [Object], hb: [Object], Be: {}, fc: {}, zc: [Object] },
ia: Eb { B: null, k: null },
Xa: ch { ta: [Circular], ba: [Object], INTERNAL: [Object] },
cd: 0,
ge: null,
K: Dg { wa: [Object], hb: [Object], Be: {}, fc: {}, zc: [Object] } },
path: G { o: [ 'Ratings', 'ratingID1', 'place_ID_' ], Y: 0 },
m:
jf {
xa: false,
ka: false,
Ib: false,
na: false,
Pb: false,
oa: 0,
kb: '',
bc: null,
xb: '',
Zb: null,
vb: '',
g: Ae {} },
Kc: false,
then: undefined,
catch: undefined }
,鉴于此数据库键仅包含整数值,这是相当不可思议的。
非常感谢任何帮助,如有必要,我可以提供更多信息。
修改 我现在尝试使用async / await关键字加上一次('value).then(snapshot =&gt; snapshot.val())来获取值,但这不会编译,或者如果我删除async / await,承诺永远不会解决。
答案 0 :(得分:2)
从数据库中检索值是异步。
如果查看https://firebase.google.com/docs/database/web/read-and-write,它会有一次检索值的示例:
var userId = firebase.auth().currentUser.uid; return firebase.database().ref('/users/' + userId).once('value').then(function(snapshot) { var username = (snapshot.val() && snapshot.val().username) || 'Anonymous'; // ... });
您可以使用on('value')
来接收值的更新,也可以使用once('value')
获取一次。两者都返回通过snapshot
的承诺,而snapshot.val()
将为您提供该节点的值。
因此您可以像这样检索值:
const place_ID_ = await admin.database().ref(`Ratings/${event.params.rating_uid}/place_ID_`).once('value').then(snapshot => snapshot.val());
console.log('place_ID_:', place_ID_);
Psst,所有那些下划线都非常丑陋,只是说,尝试camelCase;)如果它们已经是字符串,或者你正在与其他字符串连接,则不需要在String()
中包装变量。您可以将const
用于不更改的变量,而不是let
。