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

时间:2019-05-13 10:29:54

标签: arrays firebase flutter google-cloud-firestore

使用flutter,当使用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)});
          }

两次执行此功能时,firestore中的数组“ nauseaLevel”将仅添加一个“痛苦”值,而忽略第二个。

数组nauseaTime可以正常工作,因为值不同。

4 个答案:

答案 0 :(得分:1)

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

您可以做的是阅读文档,将客户端中的阵列修改为所需的形式(包括重复项),然后将阵列字段写回Firestore。您可以通过事务原子地完成此操作。

答案 1 :(得分:0)

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

  

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

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

但是,为了避免造成误解,您可以在数组中添加重复的元素,但前提是您必须阅读整个数组客户端,然后进行添加(包括所有重复项),然后将其写回到数据库中。

答案 2 :(得分:0)

我在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();
}

答案 3 :(得分:0)

实际上,你可以。您需要做的是为每个数据发送一个额外的虚拟信息。因此,与其上传“StackOverflow 很棒”,您应该上传一个对象,该对象的字段包含您想要的数据,可能还有用户名或随机生成的 id 字段

这是一个例子:

const uploadSameComment = () => {
const post = // retrieve the post you want to update
const commentObj = // this can also be a let declaration, I leave that to you

// we will need these variables
let updatedComments
let commentsInFirestore
let isFirestoreHasSameComment

// interpolate the number to indicate it is mutated and also to be able to store
// you can further sophisticate the random constant
// I'll leave it like this for example purposes
const random = `--sameCommentWithRandomProperty${Math.floor(Math.random() * 10)}`

// wait for the comments
await post.get().then(doc => doc.exists && commentsInFirestore = doc.data().comments)


// check if the comment you want to upload and the comment array of that specific 
// post has the same comment already by mapping through the comments that are 
// currently not updated in the firebase
   commentsInFirestore && commentsInFirestore.map(item => {
     if(item.comment == commentObj.comment) {
        item.postId += random
        isFirestoreHasSameComment = item
     }
  })

await post.update({ 
  comments:firebase.firestore.FieldValue.arrayUnion(
    isFirestoreHasSameComment 
      ? isFirestoreHasSameComment 
      : commentObj
    )
  })
}

现在,您可以添加任意数量的重复项来触发!

此外,将来您可以忽略这些评论如果您愿意使用我们在中指定的标签搜索它们随机 恒定。