如何在Google Firestore中存储已排序的列表

10

您如何在Google Firestore中存储N个项目的有序列表?

例如,待办事项清单。我有一些想法,但似乎都不太明智。

您可以在项目上放置一个“位置”键,但这将需要更新所有项目的位置值,当其中一个发生更改时。

您可以将它们存储在排序数组中,并在持久化之前进行一些切割以重新排序。

我很想听听推荐的方法是什么。

4个回答

5

我使用的方法不需要更新所有文档,而只需使用“position”属性来更新您要排序的文档(我认为这是Trello列表的工作方式)。

假设您有一个包含5个元素的列表:

- A (position: 1)
- B (position: 2)
- C (position: 3)
- D (position: 4)
- E (position: 5)

假设你将 C 拖到 A 和 B 之间(这是最简单的计算),那么你会得到:
- A (position: 1)
- C (old position: 3, new?) <---- you need to calculate this new position
- B (position: 2)
- D (position: 4)
- E (position: 5)

此时,您只需要知道前一个元素的位置和下一个元素的位置:

(A + B) / 2 = 1.5

1.5 是 "C" 的新位置。

- A (position: 1)
- C (position: 1.5) <--- update only this doc in your db
- B (position: 2)
- D (position: 4)
- E (position: 5)

让我们把C再次移动到最新的位置。在这种情况下,您没有下一个元素,所以要做last + 0.5

- A (position: 1)
- B (position: 2)
- D (position: 4)
- E (position: 5)
- C (new position: 5.5)

最后,如果你没有前一个元素…… 首先要检查是否有下一个元素,如果有,则执行:next / 2,否则将其设为0.5
让我们把C移到最上面:
- C (new position: A / 2 = 0.5)
- A (position: 1)
- B (position: 2)
- D (position: 4)
- E (position: 5)

最终,您将会涉及除以浮点数,但这不是问题,因为它们几乎无限大(取决于您使用的语言)。

感谢@singuerinc分享这个解决方案,这是目前最有效/简单的解决方案,非常易于实现和维护,非常强大!非常感谢! - Chun Pin Chen

2
你可以在Firestore中存储两个列表。一个包含实际数据(无序),另一个是id到顺序的映射。
以下是一个Dart示例:
你可以在Firestore中存储两个列表。一个用于实际数据(无序),另一个用于将id映射到顺序。
以下是一个Dart示例:
main() {

  List myList = [
    {'id': 'red', 'test': 'some data'},
    {'id': 'green', 'other': 'some other data'},
    {'id': 'blue'},
  ];

  List myOrderList = ['green', 'red', 'blue'];

  List orderByOtherList(List theList, String commonField, List orderList) {
    List listOut = [];
    orderList.forEach((o) => listOut.add(theList.firstWhere((m) => m[commonField] == o)));
    return listOut;
  }

  print(myList);
  print(orderByOtherList(myList, 'id', myOrderList));
}

这是在DartPad上的示例:https://dartpad.dartlang.org/dc77acd6e4cfce608796a51cda3ee9ad 然后使用rxdart中的combineLatest2将流合并,以便在任一列表更改时对应用程序中的实际列表进行排序。
此示例使用Dart编写,但您应该能够在其他语言中创建类似的内容。

很棒的解决方案!但是Firestore有1MB的文档大小限制,对于大型应用程序也需要考虑这一点。 - Chun Pin Chen

1
Firestore没有“存储排序列表”作为其功能之一。它将使用您定义的文档字段的值构建集合中文档的索引。然后,您可以基于该索引对文档进行排序。您如何处理这些文档字段完全取决于您自己。如果您需要重新编写值以适应所需的排序方式,请这样做。

谢谢,我想太多了。 只需将已排序的数组存储为文档字段,并每次更新即可。 - user2420484
2
这似乎是一个不好的方法,因为每次文档写入都会收费。对于 OP 的待办事项列表示例,每次重新排序待办事项都需要进行 N 次 Firestore 文档写入。这不仅需要时间,而且会花费很多钱。 - Patrick
我希望我有一个。不幸的是,我认为更好的方法是由Firestore团队实现的。 - Patrick
@Patrick 你也可以自由地提交一个功能请求。http://firebase.google.com/support/contact/bugs-features - Doug Stevenson

0

您可以使用id:data分支和id:idPrevious分支来使用实时数据库。

基本上您正在创建一个链接列表,这将允许您在添加时进行两次写入,而在删除时进行一次写入。重新排序/移动将需要重写三个内容。以下是一个示例:

原始

id:data 1:A, 2:B, 3:C, 4:D, 5:E

id:idPrevious 1:0, 2:1, 3:2, 4:3, 5:4

修改后 ABCDE->ADBCE

id:data 1:A, 2:B, 3:C, 4:D, 5:E - 保持不变

id:idPrevious 1:0, 2:4, 3:2, 4:1, 5:3 - 最多更改3项

进一步的细节:

5:3 发生在从订单中删除 D 时。 4:1 发生在将 D 分配到一个项目后。 2:4 发生在 D 与另一个数据块共享 idPrevious,因此感到抱歉将其踢出,它提供其id作为被踢出的项目的idPrevious。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接