Flutter Firestore查询2个集合

时间:2019-07-25 14:18:00

标签: firebase flutter dart google-cloud-firestore

问题已更新

如何查询2个具有1对1关系的集合?我有一个愿望清单集合,每个愿望清单文档如下所示:

documentID: "some-wishlist-id",
modified: "1564061309920",
productId: "2tqXaLUDy1IjxLafIu9O",
userId: "0uM7Dt286JYK6q8iLFyF4tG9cK53"

还有一个产品集合,每个产品文档如下所示。愿望清单集合中的productId将是产品集合中的documentID:

documentID: "2tqXaLUDy1IjxLafIu9O",
dateCreated: "1563820643577",
description: "This is a description for Product 9",
images: ["some_image.jpg"],
isNegotiable: true,
isSold: false,
rentPrice: 200,
sellPrice: 410,
title: "Product 9",
totalWishLists: 0,
userId: "0uM7Dt286JYK6q8iLFyF4tG9cK53"

注意:要清楚,愿望清单查询应返回我需要迭代以检索产品的文档列表。

不确定在这种情况下是否需要使用数据流或期货,但这是我到目前为止的用途:

Future<Product> getProduct(String documentId) {
return Firestore.instance
    .collection(APIPath.products())
    .document(documentId)
    .get()
    .then((DocumentSnapshot ds) => Product.fromMap(ds.data));
}

Query getWishListByUser(userId) {
    return Firestore.instance
        .collection(APIPath.wishlists())
        .where('userId', isEqualTo: userId);
}

Future<List<Product>> getProductsWishList(userId) async {
    List<Product> _products = [];

    await getWishListByUser(userId)
        .snapshots()
        .forEach((QuerySnapshot snapshot) {
      snapshot.documents.forEach((DocumentSnapshot snapshot) async {
        Map<String, dynamic> map = Map.from(snapshot.data);
        map.addAll({
          'documentID': snapshot.documentID,
        });

        WishList wishList = WishList.fromMap(map);

        await getProduct(wishList.productId).then((Product product) {
          print(product.title); // This is printing
          _products.add(product);
        });
      });
    });

    // This is not printing
    print(_products);

    return _products;
  }

谢谢

2 个答案:

答案 0 :(得分:0)

对于任何数据库,您通常需要将多个表中的数据连接起来以建立视图。

在关系数据库中,可以使用JOIN子句通过一条语句从这些多个表中获取数据。

但是在Firebase(以及许多其他NoSQL数据库)中,没有内置的方式可以从多个位置连接数据。因此,您将必须在代码中执行此操作。

创建心愿单模型:

class Wishlist {

  Wishlist({
    this.id,
    this.modified,
    this.productId,
    this.userId
  });

  final String id;
  final String modified;
  final String productId;
  final String userId;

  Wishlist.fromMap(json)
    : id = json['id'].toString(),
      modified = json['modified'].toString(),
      productId = json['productId'].toString(),
      userId = json['userId'].toString();
}

在您的API文件中,执行以下操作:

final Firestore _fireStore = Firestore.instance;    

getWishList(wishlistId) async {
  return await _fireStore.collection('wishlists').document(wishlistId).get();
}

getProduct(productId) async {
  return await _fireStore.collection('product').document(productId).get();
}

Future<List<Product>>getProductsWishList(wishlistId) async {

  var _wishlists = null;
  List<Product> _products = []; // I am assuming that you have product model like above

  await getWishList(wishlistId).then((val) {
    _wishlists = Wishlist.fromMap(val.data);

    _wishlists.forEach((wish) {
      await getProduct(wish.productId).then((product) {
          _products.add(product));
      });
    });
  });

  return _products;
}

答案 1 :(得分:0)

我上周末找到了解决方案,但忘了发布。想通了,如果有人遇到这个问题,我现在就去做。

我使用了SELECT itemid, a.amount, (amount * ItemUnitPrice) 'total' FROM ((SELECT itemdb.ItemId, itemdb.ItemName, ISNULL(COUNT(SalesStatisticsDb.ItemId), 0) AS 'amount', ItemDb.ItemUnitPrice FROM dbo.SalesStatisticsDb RIGHT JOIN ItemDb ON SalesStatisticsDb.ItemId = ItemDb.ItemId WHERE (SUBSTRING(SalesStatisticsDb.UpdateTime, 6, 2) = '01') GROUP BY ItemDb.ItemId, ItemDb.ItemName, ItemDb.ItemUnitPrice UNION ALL SELECT itemdb.ItemId, itemdb.ItemName, COUNT(SalesStatisticsDb.ItemId) AS 'amount', ItemDb.ItemUnitPrice FROM dbo.SalesStatisticsDb RIGHT JOIN ItemDb ON SalesStatisticsDb.ItemId = ItemDb.ItemId WHERE (SUBSTRING(SalesStatisticsDb.UpdateTime, 6, 2) = '02') GROUP BY ItemDb.ItemId, ItemDb.ItemName, ItemDb.ItemUnitPrice)) AS a GROUP BY itemid, amount, ItemUnitPrice StreamBuilder的组合。不确定是否有更好的答案,也许合并多个流?但这对我有用。

FutureBuilder