在Cloud函数中,如何从另一个集合中加入以获取数据?

时间:2019-01-24 13:21:58

标签: node.js firebase push-notification google-cloud-firestore google-cloud-functions

我正在使用Cloud Function向移动设备发送通知。我在Firestore db.taskDetails.aggregate([ {$unwind:"$counter_offer"}, {$match:{_id:ObjectId('5bfbc0f9ac2a73278459efc1')}}, {$sort:{"counter_offer.Counter_offer_Amount":1}}, {$unwind:"$counter_offer"}, {"$group" : {_id:"$_id", counter_offer:{ $push: "$counter_offer" }, "task_name": { "$first": "$task_name"}, "task_status": { "$first": "$task_status"}, "task_location": { "$first": "$task_location"}, }} ]).pretty() clientDetail中有两个集合。我在两个集合中都有clientPersonalDetail相同,但是日期存储在clientID中,名称存储在clientPersonal中。

看看:

clientDetail

这是我的完整代码:

ClientDetail -- startDate
             -- clientID
             .......

ClientPersonalDetail -- name
                     -- clientID
                     .........

} );

以上功能显示的是这样的对象

exports.sendDailyNotifications = functions.https.onRequest(  (request, response) => {
var getApplicants = getApplicantList();
console.log('getApplicants', getApplicants);

cors(request, response, () => {
  admin
    .firestore()
    .collection("clientDetails")
    //.where("clientID", "==", "wOqkjYYz3t7qQzHJ1kgu")
    .get()
    .then(querySnapshot => {
      const promises = [];
      querySnapshot.forEach(doc => {
        let clientObject = {};
        clientObject.clientID = doc.data().clientID;
        clientObject.monthlyInstallment = doc.data().monthlyInstallment;
        promises.push(clientObject);
      });

      return Promise.all(promises);
    }) //below code for notification
    .then(results => {
      response.send(results);
      results.forEach(user => {
        //sendNotification(user);
      });
      return "";
    })
    .catch(error => {
      console.log(error);
      response.status(500).send(error);
    });
});

但是我需要在通知中不显示ClientID,所以我必须加入clientPersonal集合才能使用clientID来获取名称。 应该怎么办?

我如何创建另一个函数,该函数仅通过将clientID作为参数传递来返回名称,并等待它返回name。 有人可以帮忙吗??

3 个答案:

答案 0 :(得分:1)

  

但是我需要在通知中不显示ClientID,所以我必须加入clientPersonal集合才能使用clientID来获取名称。应该怎么办?

不幸的是,Firestore中没有JOIN子句。 Firestore中的查询很浅。这意味着它们仅从运行查询的集合中获取项目。在单个查询中无法从两个顶级集合中获取文档。 Firestore不一次性支持跨不同集合的查询。单个查询只能使用单个集合中的文档属性。

  

如何创建另一个函数,该函数仅通过将clientID作为参数传递来返回名称,并等待它返回名称。

因此,我能想到的最简单的解决方案是首先查询数据库以获取clientID。拥有此ID后,请在回调中进行另一个数据库调用,以便获得相应的名称。

另一种解决方案是将用户名添加为ClientDetail下的新属性,以便您只能查询数据库一次。这种做法称为denormalization,是Firebase的常见做法。如果您不熟悉NoQSL数据库,建议您观看此视频Denormalization is normal with the Firebase Database,以更好地理解。它用于Firebase实时数据库,但相同的规则适用于Cloud Firestore。

此外,在复制数据时,需要记住一件事。用与添加数据相同的方式,您需要对其进行维护。换句话说,如果您想更新/删除项目,则需要在它存在的每个位置进行。

答案 1 :(得分:1)

“更轻松”的解决方案可能是重复数据。这在NoSQL世界中很常见。

更准确地说,您将在ClientDetail集合中的文档中添加客户端name的价值。

答案 2 :(得分:1)

在这种情况下,您可以使用两个额外的功能来使代码清晰。一个将从集合function checkDateRange(startDate: string, endDate: string, fillDate: string): boolean { if (fillDate > startDate && fillDate < endDate) { const _fillDate = moment(fillDate).utc(); return _fillDate.isBetween(startDate, endDate, null, '[]'); } return false; } 中读取所有文档的函数,而不是获取所有字段,而是仅获取ClientDetail。然后调用另一个函数,该函数将扫描集合ClientID中的所有文档,并仅检索具有ClientID的部件。比较这两个是否匹配,然后在匹配的地方进行任何操作。

您可以参考Get started with Cloud Firestore文档,了解如何从Firestore创建,添加和加载文档。

您的ClientPersonalDetail应该看起来像这样:

package,json

我自己做了一些编码,这是我的example code in GitHub。通过部署此功能,将扫描一个集合中的所有文档,并比较另一集合中的ClientID。当找到匹配项时,将记录一条消息,否则将记录一条与ID不匹配的消息。您可以使用此函数的工作原理,并在您的代码中使用它。