扑扑中的Firebase复杂查询

时间:2019-05-30 23:18:33

标签: firebase flutter dart google-cloud-firestore

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

我尝试将多个.where()语句链接在一起,但这并不能产生我需要的效果,我在另一篇文章中读到,多个.orderBy()语句将破坏查询,但是为了检查另一个诸如价格之类的字段,输出告诉我我需要先定价orderBy()。可以应用任何数量的这些过滤器,或者取决于设置,它们都不可以应用。我在底部使用lastVisible变量作为.startAfter的单独函数,以获取更多产品。有什么方法可以产生我想通过这种方式产生的查询吗?我还想知道是否可以做类似.where('field',isEqualTo:x或y或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中创建索引以外,我没有任何错误。

1 个答案:

答案 0 :(得分:1)

  

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

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

  

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

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

  

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

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

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

  

状态{code = FAILED_PRECONDITION,描述=查询需要索引。

因此,请不要忘记在Firebase控制台中创建索引。

  

有什么办法可以产生我想通过这种方式进行的查询?

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

  

我还想知道是否可以做类似.where('field',isEqualTo:x或y或z)的事情。

不,这是不可能的,但是有一项工作流程可以帮助您实现同一目标。为此,请从以下帖子中查看我的答案:

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