使用.where()
查询文档时,我很难提取子集合。我不断收到错误消息:
TypeError: collectionData.where(...).collection is not a function
如果我使用标准的.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;
答案 0 :(得分:1)
在您的Hotels
类中,在create
方法中,hotelCollection
应该是CollectionReference
,因为您调用了add()
方法。
另一方面,在list
方法中,由于您进行了hotelCollection.collection('hotels').get()
,这意味着hotelCollection
应该是DocumentReference
(或者hotelCollection
是等于admin.firestore()
,似乎并非如此……)。
因此,如果您希望这两种方法具有相同的签名,则应传递与查询返回的文档的CollectionReference
子集合相对应的hotels
。
因此,首先,按如下所示修改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;
}
});
});
});
您首先执行查询,然后通过QueryDocumentSnapshot
属性获取QuerySnapshot
中的第一个docs
,然后获取其DocumentReference
,最后获取文档的{{ 1}}子集合,以便将其传递给hotels
方法。
请注意,以上代码基于两个假设:
Hotels
值,因此使用countryCode
; docs[0]
变量保存“数据库”屏幕截图中显示的集合,即屏幕截图左侧的集合。最后,请注意,如果要从GET HTTPS请求的URL中获取collectionData
的值(即,将硬编码的countryCode
值替换为通过GET查询字符串传递的变量值)参数),则应使用VN
,请参见https://flaviocopes.com/express-get-query-variables/