【问题标题】:How do I do a first-in-first-out system in Flutter/Firestore?如何在 Flutter/Firestore 中实现先进先出系统?
【发布时间】:2021-05-23 07:11:49
【问题描述】:

我正在构建一个与库存管理系统非常相似的应用。我现在的障碍是 Firestore 中允许的查询数量,因为它不允许多个 .where()。

所以使用库存管理系统的概念,我们创建了一个集合:

我们将其命名为 'InventoryCollection'。假设它有 3 个字段:

- ItemID
- ItemName
- DateAdded

'InventoryCollection' 中的每个文档都有一个名为 'PurchaseHistory' 的子集合: 它有字段:

- PurchaseID (auto generated document id)
- ItemID (from parent collection document)
- PurchaseDate
- Quantity

困境:如何使用先进先出的概念来扣除物品的数量? 因此,假设 Item1 有 4 PurchseHistory 数据。假设其中一个的数量为 0,因为它们已经售出。

- PurchaseID: 12340 
- ItemID: 00001
- PurchaseDate: 01-feb-2021
- Quantity: 0

- PurchaseID: 12341(auto generated document id)
- ItemID: 00001
- PurchaseDate: 02-feb-2021
- Quantity: 10

- PurchaseID: 12342
- ItemID: 00001
- PurchaseDate: 03-feb-2021
- Quantity: 5

- PurchaseID: 12343
- ItemID: 00001
- PurchaseDate: 03-feb-2021
- Quantity: 15

我需要找到一种方法来检索 PurchaseId 12341 以使用以下参数获取“First In”。然后我可以自己想办法“先出”:

  • 获取所有 ItemID 为 00001 的 PurchaseHistory 文档
  • 仅获取具有 1 个或多个 Quantity 的文档
  • 按 PurchaseDate 对数据进行排序,以便第一个结果将是 2 月 2 日的条目
  • 将查询结果限制为 1 只获取 2 月 2 日的文档
  • 获取要在以下方法中使用的该文档的 purchaseID:
void _deductQuantity(String itemId, String PurchaseID {
  final itemCollection = FirebaseFirestore.instance.collection('InventoryCollection').doc(ItemId).collection('PurchaseHistory').doc(purchaseID);
  itemCollection.update({
    'Quantity':  _quantity - int.parse(_editItemQuantityController.text.trim()),
  });
}

在我看来,查询是这样的:

String purchaseIdStream;


   final docRef = FirebaseFirestore.instance.collection('InventoryCollection').doc(ItemId).collection('PurchaseHistory').doc();
    
    purchaseIdStream = await docRef
        .where('ItemId', isEqualTo: ItemId)
        .where('Quantity', isGreaterThan: 0)
        .orderBy('PurchaseDate')
        .get();
     var _id = purchaseIdStream.ref.documentID;

我完全理解 Firebase 不允许 orderby,如果您在 .where 中没有该字段用于购买。所以绝对不可能在上面的代码上做到这一点。因为我已经有 2 个 where 和第 3 个 where 是不可能的。

我知道我必须进行服务器端过滤而不是多个 .where 但是,我只是前端开发人员。我对后端概念的理解非常有限。所以我需要关于如何在 dart/flutter 中实现这一点的糟糕指导。

我们将不胜感激任何建议。谢谢!

【问题讨论】:

标签: firebase flutter dart google-cloud-firestore


【解决方案1】:

首先,.where() 属性仅适用于 CollectionReference,不适用于 DocumentReference。删除docRef 中的.doc(ItemId)。我认为它应该在那之后工作。

如果没有,获取数据并手动排序,如下所示:

final purchaseIdList =
    await docRef.where('ItemId', isEqualTo: ItemId).where('Quantity', isGreaterThan: 0).get();
purchaseIdList.docs.sort((QueryDocumentSnapshot a, QueryDocumentSnapshot b) =>
    (a.data()['PurchaseHistory']['PurchaseDate'] as String)
        .compareTo(b.data()['PurchaseHistory']['PurchaseDate'] as String));
final fifoId = purchaseIdList.docs[0].get('PurchaseId');

如果我遗漏了什么,请告诉我。我会编辑答案。

【讨论】:

  • 等等,你需要它作为流吗?
  • 感谢您的回答,但我不需要它作为流。我只需要在按下按钮后获取购买历史中具有数量的最早文档的 PurchaseID。
  • 好吧,我的答案不是流,哈哈。我只是复制了你写的东西。我会编辑那个。 purchaseIdList 的最终值应该是您需要的购买历史的排序列表。而fifoId是最早文档的PurchaseId
  • 现在我已经编辑了答案。检查一下,看看它是否正常工作
  • 谢谢!我很抱歉,因为当我回答时我正在工作,我应该在回答之前先阅读它。但我现在有机会测试您的答案,结果如下: 解决方案 1:删除 collectionreference 中的 itemId - 这导致错误:初始 orderBy() 字段 '[[FieldPath([PurchaseDate]), false]][当调用不等式运算符时,0][0]' 必须与 where() 字段参数 'FieldPath([quantity])' 相同。解决方案2:使用您的代码导致此错误:无效值:有效值范围为空:0
【解决方案2】:

documentation 表示如果一个字段在orderBy 中使用,它也应该在第一个where 中使用。

citiesRef.where("population", ">", 100000).orderBy("population").limit(2);

【讨论】:

    【解决方案3】:

    答案是对 itemId 和数量使用 where,然后在 Dart 中做其余的过滤器:

    var listOfDocs = await docRef
        .where('ItemId', isEqualTo: ItemId)
        .where('Quantity', isGreaterThan: 0)
        .get();
    
    docs.sort((prev, next) => (prev.data()['PurchaseDate'] as Timestamp)
        .compareTo(next.data()['PurchaseDate'] as Timestamp));
    
    final desiredDocId = docs.first.id;
    
    print(desiredDocId);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-15
      • 1970-01-01
      • 2019-12-09
      • 1970-01-01
      • 1970-01-01
      • 2021-03-08
      相关资源
      最近更新 更多