javascript - 带子集合的 Firebase 查询

标签 javascript firebase google-cloud-firestore

当我使用 .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;

数据库 enter image description here

最佳答案

在您的 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/

相关文章:

javascript - Firebase云函数错误: Function returned undefined,预期的Promise或值

javascript - 火炉吓坏了

java - removeEventListener() 不是 Firebase Firestore 的一部分吗?

javascript - 以 json 形式返回 protobuf 对象

javascript - 设备进入休眠状态后,计时器是否会在移动浏览器中继续触发?

javascript - Wicket AjaxCallListener getPrecondition 方法不起作用

javascript - 'npm i' 和 'npm install' 有什么区别?

javascript - 使用 javascript 从 firebase 检索所有数据

javascript - 使用 Firebase Cloud Functions 更新用户

angular - Kendo Sortable for Angular - 获取新的索引位置