当我使用 .where()
查询文档时,我在提取子集合时遇到困难。我不断收到错误:
类型错误:collectionData.where(...).collection不是函数
如果我使用标准的 .doc()
它可以工作,而 .where()
则不起作用。
hotels
是主集合中每个文档的子集合。 hotelCollection
假设将提取的数据传递给要解析和执行的类。
index.js
exports.hotels = functions.https.onRequest((req,res) => {
cors(req, res, () => {
const countryCode = req.url.replace('/', '').toUpperCase();
const hotelCollection = collectionData.where('countryCode', '==', 'VN').collection('hotels');
switch (req.method) {
case 'GET':
Hotels.list(hotelCollection, req, res);
break;
case 'POST':
Hotels.create(hotelCollection, req, res);
break;
default:
res.status(405).send({error: 'An error occurred!'});
break;
}
})
});
hotel.js
let admin = require('firebase-admin');
class Hotels {
static list(hotelCollection, req, res) {
let hotelData = [];
return hotelCollection.collection('hotels').get()
.then(hotels => {
hotels.forEach(hotel => {
hotelData.push(hotel.data());
});
return hotelData;
})
.then(hotelData => {
return res.status(200).send(hotelData);
})
.catch(err => {
return res.status(404).send('Error finding hotel for this country: ' + err);
});
}
static create(hotelCollection, req, res) {
return hotelCollection.add(req.body)
.then(result => {
return res.status(200).send('Hotel has been added!');
})
.catch(err => {
return res.status(404).send('Error adding hotel for this country: ' + err);
});
}
}
module.exports = Hotels;
最佳答案
在您的 Hotels
类的 create
方法中,hotelCollection
应为 CollectionReference
,因为您调用了 add()
方法。
另一方面,在 list
方法中,由于您执行 hotelCollection.collection('hotels').get()
,这意味着 hotelCollection
应为 DocumentReference
(或者 hotelCollection
等于 admin.firestore()
,但情况似乎并非如此......)。
因此,如果您希望这两个方法具有相同的签名,则应该传递与您返回的文档的 hotels
子集合相对应的 CollectionReference
查询。
因此,首先按如下方式调整 Hotels
类:
class Hotels {
static list(hotelCollection, req, res) {
let hotelData = [];
return hotelCollection.get() // <-- !!! See change here
.then(hotels => {
hotels.forEach(hotel => {
hotelData.push(hotel.data());
});
return res.status(200).send(hotelData); // !!! <-- and also here, we removed a then()
})
.catch(err => {
return res.status(404).send('Error finding hotel for this country: ' + err);
});
}
static create(hotelCollection, req, res) {
return hotelCollection.add(req.body)
.then(result => {
return res.status(200).send('Hotel has been added!');
})
.catch(err => {
return res.status(404).send('Error adding hotel for this country: ' + err);
});
}
}
<小时/>
然后,按如下方式调用:
exports.hotels = functions.https.onRequest((req,res) => {
cors(req, res, () => {
const countryCode = req.url.replace('/', '').toUpperCase();
const countryQuery = collectionData.where('countryCode', '==', 'VN');
countryQuery.get()
.then(querySnapshot => {
const countryDocRef = querySnapshot.docs[0].ref;
const hotelCollection = countryDocRef.collection('hotels');
switch (req.method) {
case 'GET':
Hotels.list(hotelCollection, req, res);
break;
case 'POST':
Hotels.create(hotelCollection, req, res);
break;
default:
res.status(405).send({error: 'An error occurred!'});
break;
}
});
});
});
您首先执行查询,然后获取 QuerySnapshot
的第一个 QueryDocumentSnapshot
通过 docs
属性,然后获取其 DocumentReference
,最后获取文档的 hotels
子集合,以便将其传递给 酒店
方法。
请注意,上面的代码基于两个假设:
- 只有一个文档具有给定的
countryCode
值,因此使用docs[0]
; collectionData
变量保存“数据库”屏幕截图中显示的集合,即屏幕截图左侧的集合。
最后,请注意,如果您想从 GET HTTPS 请求的 URL 获取 countryCode
的值(即将硬编码的 VN
值替换为变量值)通过 GET 查询字符串参数传递),您应该使用 req.query
,请参阅 https://flaviocopes.com/express-get-query-variables/
关于javascript - 带子集合的 Firebase 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60462561/