【问题标题】:Firebase Complex Queries In FlutterFlutter 中的 Firebase 复杂查询
【发布时间】:2019-10-16 14:46:09
【问题描述】:

我正在使用 Firebase 中的一个集合来存储有关产品的信息。以前,我只是获取所有产品,然后在客户端对它们应用过滤器。有人告诉我,我需要通过查询应用这些过滤器,以减少 Firebase 需要的读取次数,因为会有大量产品。

我尝试将多个 .where() 语句链接在一起,但这并不能产生我需要的效果,我在另一篇文章中读到多个 .orderBy() 语句会破坏查询,但为了检查另一个输出的价格等字段告诉我我需要先 orderBy() 价格。可以应用任意数量的这些过滤器,或者它们都不能应用,具体取决于设置。我在一个单独的函数中使用底部的 lastVisible 变量作为 .startAfter 来获取更多产品。有什么方法可以产生我想以这种方式进行的那种查询吗?我还想知道是否可以执行类似 .where('field', isEqualTo: x or y or z) 的操作。

    Query productQuery = Firestore.instance.collection('Products');

    if(selectedCategories != null)
    for(int i = 0; i < selectedCategories.length; i++)
      productQuery = productQuery.where('category', isEqualTo: selectedCategories[i]);

    if(minPrice > 0 && maxPrice > 0)
    {
      productQuery = productQuery.orderBy('price').where('price', isGreaterThanOrEqualTo: minPrice).where('price', isLessThanOrEqualTo: minPrice);
    }
    else if(minPrice > 0)
      productQuery = productQuery.orderBy('price').where('price', isGreaterThanOrEqualTo: minPrice);

    else if(maxPrice > 0)
      productQuery = productQuery.orderBy('price').where('price', isLessThanOrEqualTo: maxPrice);

    if(!showUnavailableItems)
      productQuery = productQuery.where('status', isEqualTo: 'available');

    switch(selectedCondition)
    {
      case 'Acceptable':
        productQuery = productQuery
                      .where('condition', isEqualTo: 'Acceptable')
                      .where('condition', isEqualTo: 'Good')
                      .where('condition', isEqualTo: 'Very Good');
        break;
      case 'Good':
        productQuery = productQuery
                      .where('condition', isEqualTo: 'Acceptable')
                      .where('condition', isEqualTo: 'Good');
        break;
      case 'Very Good':
        productQuery = productQuery
                      .where('condition', isEqualTo: 'Acceptable');

        break;
      default:
        break;
    }

    productQuery = productQuery.orderBy('id');

    QuerySnapshot myQuery = await productQuery.getDocuments();
    List<DocumentSnapshot> productSnaps = myQuery.documents;
    print("INITIAL PRODUCT SNAPS LENGTH: ${myQuery.documents.length}");

    if(productSnaps.length != 0)
      lastVisible = productSnaps[productSnaps.length -1].data['id'];

应用条件或类别过滤器时,结果始终为 0 个文档。分别使用 minPrice 和 maxPrice 过滤器有效,但一起使用也会返回 0 个产品。除了在 Firebase 中创建索引的错误之外,我没有收到任何错误。

【问题讨论】:

    标签: firebase flutter dart google-cloud-firestore


    【解决方案1】:

    有人告诉我,我需要通过查询应用这些过滤器以减少读取次数

    这是正确的,因为在 Firestore 中,一切都与读写次数有关。

    我尝试将多个 .where() 语句链接在一起,但这并没有产生我需要的效果

    你为什么这么说?我已经多次使用where() 函数来过滤 Cloud Firestore 数据库中的数据,并且从未失败过。

    我在另一篇文章中读到多个 .orderBy() 语句会破坏查询

    不是是真的!请从以下帖子中查看我的答案:

    还请记住,如果您正在使用多个 orderBy() 方法调用,您会收到类似以下的警告:

    Status{code=FAILED_PRECONDITION, description=查询需要索引。

    所以不要忘记在 Firebase 控制台中创建索引。

    有没有什么方法可以产生我想要的那种查询?

    是的,您可以使用您已经提到的所有选项。

    我也想知道是否可以执行类似 .where('field', isEqualTo: x or y or z) 之类的操作。

    不,这是不可能的,但有一种解决方法可以帮助您实现同样的目标。为此,请参阅我在以下帖子中的回答:

    因此,不要使用数组,而是使用映射并链接多个 where() 调用。

    【讨论】:

    • 感谢您的回复。我的意思是.where()语句是,当条件的交换机语句为Very Good查询返回使用Very Good的所有产品condition,但选择Good时,我想要它返回所有将condition 设置为Very GoodGood 的产品,但是当这种情况运行时,它总是返回0 个没有错误代码的产品。
    • 当您想要将条件设置为Very GoodGood 时,这意味着您正在寻找OR 子句(以SQL 术语),目前Cloud 中不支持该条件火库。如需解决方案,请参阅我在此 post 中的回答。
    • 我能够重新设计 Firebase 文档的数据结构,使其不需要任何基于 OR 逻辑的查询。感谢您在上一篇文章中提供指向 Firebase 限制的链接。
    • 哇,竟然不支持OR?我想知道为什么有这么多人仍在使用 Firebase,即使它在这种常见的情况下也不起作用。我可以说 Firebase 查询很弱吗?
    • @Bagusflyer 这个答案来自 2019 年。现在,在 2020 年,我们可以选择使用 10 equality (==) clauses on the same field with a logical OR ;)
    猜你喜欢
    • 2021-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-17
    相关资源
    最近更新 更多