如何在两个不同文档之间的Firestore上进行复合查询?

时间:2019-11-02 16:57:40

标签: javascript firebase google-cloud-firestore

我在Firebase Firestore上有一个项目,我想在同一个子集合下的两个文档之间执行复合查询。我已经创建了Firestore所需的索引,并且如果字段在同一文档中,查询将完美执行。

举例说明我的情况:

采用以下结构:

- Users (root collection)
  - User (document)
    - userId
    - username
    - ...
    --- Personalization (subcollection)
        --- Alerts (document)
            - myTags (array of strings)
            - ...
        --- Location (document)
            - region (string)
            - ...

我想执行一个查询,该查询首先验证用户region/Users/{userId}/Personalization/Location)是否等于参考值。如果是这样,我希望它验证数组myTags/Users/{userId}/Personalization/Alerts)是否包含某个标记。

这是我到目前为止可以获得的最接近的数字:

db.collectionGroup('Personalization').where('region', '==', 'California').where('myTags', 'array-contains', 'Macbook')
    .get().then(querySnapshot => {
        if (querySnapshot.empty) {
            console.log('Result is empty');
        } else {
            console.log('Result found. ', querySnapshot.size, ' result(s).');
        }
        querySnapshot.forEach(doc => {
            console.log(doc.id, ' => ', doc.data());
        });
    }).catch(error => {
        console.error(error);
    });

如果我的所有字段都在同一个文档下,则该查询非常有效,例如:

    --- Personalization (subcollection)
        --- Alerts (document)
            - myTags (array of strings)
            - region (string)
            - ...

此外,我可以使两个查询完全独立地工作,如下所示:

db.collectionGroup('Personalization').where('myTags', 'array-contains', 'Macbook').get().then(querySnapshot => {
    querySnapshot.forEach(element => {
        console.log('Search only by tag => ', element.id, ' => ', element.data());
    });

有没有一种方法可以使查询工作,同时仍在同一子集合下使用两个不同的文档,或者我必须使用同一文档进行复合查询?也许索引上有一些配置,或者类似的东西我也不知道,因为当您第一次尝试使用复合查询创建索引时,我只关注了Firebase为您提供的错误链接。

其他信息:

  • 该代码正在开发中,可以部署在Firebase Functions上,并且每次我拥有的某个集合上发生onWrite事件时,都会触发该代码。

此外,如果有人知道Firestore上的一些复合查询示例,我将不胜感激。我已经阅读了文档,并看到了Firebase团队的一些视频,它们解释了Firestore的工作原理,但我感到缺少更复杂的示例来了解Firestore的工作原理。

2 个答案:

答案 0 :(得分:2)

Firestore当前不支持逻辑OR类型查询,在逻辑OR类型查询中,您可以提供多个条件来进行匹配:

如您所见,它仅支持逻辑AND。当您提供两个where子句时,查询将仅提供同时满足这两个条件的文档。

如果要对多个条件实施逻辑或,则必须分别针对每个条件执行查询 ,并将结果合并到客户端代码中。这意味着您将要进行两个查询:

  • where('region', '==', 'California')
  • where('myTags', 'array-contains', 'Macbook')

然后等待两个查询结束并查看每个查询的结果。

答案 1 :(得分:1)

.where('region', '==', 'California').where('myTags', 'array-contains', 'Macbook')定义的compound query将不会返回两个不同的文档。

如文档(上面的链接)所述,此查询将仅返回与两个where子句匹配的文档 (“逻辑AND”)。

如同一文档中所述:

  

Cloud Firestore不支持以下类型的查询:

     
      
  • ...
  •   
  • 逻辑或查询。在这种情况下,您应该为每个OR条件创建一个单独的查询,然后将查询结果合并到您的应用中。
  •   
  • ...
  •   

如您在问题下方的评论中所述,一种解决方案是在regions文档中添加一个额外的Alert字段。