Firestore 在更新数组时不存储两个相同的值

Posted

技术标签:

【中文标题】Firestore 在更新数组时不存储两个相同的值【英文标题】:Firestore doesn't store two identical values while updating an array 【发布时间】:2019-09-30 07:18:32 【问题描述】:

使用颤振,当更新具有 2 个或更多连续相同值的数组时,firestore 只添加一个。

例子:

void updateValue() 
var now = [new DateTime.now()];
int pain =5;
 Firestore.instance.collection('Patient').document('bC2ML7LaQ1fWGOl37ZUq').collection('Symptom').document('2H6e99Bvrz6h0HBzgnyg')
            .updateData( 'nauseaLevel' : FieldValue.arrayUnion([pain]), 'nauseaTime':FieldValue.arrayUnion(now));
          

当执行此函数2次时,firestore中的数组“nauseaLevel”只会添加一个“pain”值而忽略第二个。

由于值不同,数组反胃时间按预期工作。

【问题讨论】:

【参考方案1】:

根据updating elements in an array的官方文档:

arrayUnion() 将元素添加到数组中,但只添加不存在的元素。

因此,您无法使用 arrayUnion() 函数在 Cloud Firestore 中的数组中添加重复元素。

然而,为避免误解,您可以在数组中添加重复元素,但前提是您读取整个数组客户端,添加(包含所有重复项),然后将其写回数据库。

【讨论】:

这并不完全正确。数组可以存储重复项。它只是无法使用 arrayUnion 更新重复项。 @DougStevenson 嗨,Doug,感谢您的评论。你是对的,所以我刚刚更新了我的答案以避免任何误解。希望你也收回反对票。我会很感激的。谢谢! 考虑到您可以使用他们控制台上的添加按钮添加副本,这在他们看来太愚蠢了。如果你想称它为数组,那就让它成为一个数组并打开一个常规的添加API!否则就叫它集合吧! 在意识到这一点之前浪费了一个小时的调试时间,这应该在数组联合文档中注明。【参考方案2】:

您不能使用 arrayUnion 来管理必须包含重复项的数组,从 arrayUnion 的定义中可以看出。

您可以改为读取文档,将客户端中的数组修改为您想要的(包括重复项),然后将数组字段写回 Firestore。您可以通过事务以原子方式执行此操作。

【讨论】:

你能发一组代码吗?或者只是指导我,我正在使用颤振,但我想做同样的事情【参考方案3】:

我在handling nested objects with Flutter and Firestore 上写了一篇文章,其中详细介绍了如何执行此操作。

这是我检索数组、更新数组并将其保存回 Firestore 的示例:

void AddObjectToArray() 
Exercise exercise;
Set newSet;
Firestore.instance
    .collection("exercises")
    .document("docID")
    .get()
    .then((docSnapshot) => 
  newSet = Set(10, 30), 
  exercise = Exercise.fromMap(docSnapshot.data), 
  exercise.sets.add(newSet),
  Firestore.instance.collection("exercises").document("docID").setData(exercise.toMap())
  );

还有我的练习和设置课程:

锻炼

class Exercise 
final String name;
final String muscle;


List<dynamic> sets = [];

  Exercise(this.name, this.muscle);

  Map<String, dynamic> toMap() => "name": this.name, "muscle": this.muscle, "sets": firestoreSets();

  List<Map<String,dynamic>> firestoreSets() 
    List<Map<String,dynamic>> convertedSets = [];
    this.sets.forEach((set) 
      Set thisSet = set as Set;
      convertedSets.add(thisSet.toMap());
    );
    return convertedSets;
  

  Exercise.fromMap(Map<dynamic, dynamic> map)
      : name = map['name'],
        muscle = map['muscle'],
        sets = map['sets'].map((set) 
          return Set.fromMap(set);
        ).toList();

设置

class Set 


final int reps;
  final int weight;

  Set(this.reps, this.weight);

  Map<String, dynamic> toMap() => "reps": this.reps, "weight": this.weight;

  Set.fromMap(Map<dynamic, dynamic> map)
      : reps = map["reps"].toInt(),
        weight = map["weight"].toInt();

【讨论】:

以上是关于Firestore 在更新数组时不存储两个相同的值的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Firestore 中创建和更新数字数组?

在 Firestore 中更新嵌套在 Array 中的对象

如何知道两个数组是不是具有相同的值

从 id 数组中获取 firestore 文档列表

如何在 Firestore 中进行批量更新

如何在 Cloud 函数中读取 Firestore 文档更新之前/之后的值?