更新 Firebase 会删除现有数据
Updating Firebase deletes already existing data
我正在使用 Firebase 构建一个应用程序,我最近使用此代码更新了用户词典中 "posts" 的 list/dictionary。看看:
Firebase *baseRef = [[Firebase alloc] initWithUrl:@"https://<MY-APP>.firebaseio.com"];
NSString *userPostsPath = [NSString stringWithFormat:@"users/%@/posts", userId];
NSDictionary *postRef = @{ postId : postDescription };
[baseRef updateChildValues:@{
userPostsPath : postRef
// here I'd have a similar update
}withCompletionBlock:^(NSError *error, Firebase *ref) {
handler(error, ref);
}];
这适用于第一次更新,但我第二次这样做时,所有现有的帖子都被删除了。但是,将代码更改为:
Firebase *baseRef = [[Firebase alloc] initWithUrl:@"https://tonightdb.firebaseio.com"];
NSString *usersPostsPath = [NSString stringWithFormat:@"users/%@/posts/%@/", userId, postId];
[baseRef updateChildValues:@{
usersPostsPath : postDescription,
// similar update path
}withCompletionBlock:^(NSError *error, Firebase *ref) {
handler(error, ref);
}];
正确更新 Firebase。
两者有什么区别?第一个怎么不行?
编辑
是否可以做到:
Firebase *baseRef = [[Firebase alloc] initWithUrl:@"https://<MY-APP>.firebaseio.com"];
NSString *newKey = [baseRef childByAutoId];
然后使用该键执行如下所示的更新:
[baseRef updateChildValues:@{
[NSString stringWithFormat:@"/posts/%@/", newKey] : // something
[NSString stringWithFormat:@"/posts/%@/members/<something>", newKey] : // something
withCompletionBlock:^(NSError *error, Firebase *ref) {
handler(error, ref, task);
}];
基本上是在同一个请求中对同一个路径发出多个更新,这在避免覆盖问题的同时事先不存在
您的第一个示例转换为更新说明:
"users/posts" = { "postid1": postDescription }
第二个例子翻译成:
"users/posts/postid1" = postDescription
作为一个计算机程序,Firebase 服务器对您提供的指令进行了相当字面的解释。它接受每条更新指令并将路径中的数据(=
之前的部分)替换为值(=
之后的部分)。
知道后,您可以看到在第二个示例中它将在 users/posts/postid1
处写入 postDescription
。这将替换该 post 的现有描述,但这可能是您想要的。
第二个例子在users/posts
写{ "postid1": postDescription }
。这将替换该位置的现有值,因此您实际上是用 new/updated 替换所有现有的 post。这可能不是您想要的。
更新
如果您正在创建一个新对象并将密钥散布到多个位置,您可以利用 childByAutoId
是纯客户端操作这一事实:
let newRef = ref.childByAutoId()
let newKey = newRef.key
ref.childByAppendingPath("child1").childByAppendingPath(newKey).setValue("one")
ref.childByAppendingPath("child2").childByAppendingPath(newKey).setValue("two")
我正在使用 Firebase 构建一个应用程序,我最近使用此代码更新了用户词典中 "posts" 的 list/dictionary。看看:
Firebase *baseRef = [[Firebase alloc] initWithUrl:@"https://<MY-APP>.firebaseio.com"];
NSString *userPostsPath = [NSString stringWithFormat:@"users/%@/posts", userId];
NSDictionary *postRef = @{ postId : postDescription };
[baseRef updateChildValues:@{
userPostsPath : postRef
// here I'd have a similar update
}withCompletionBlock:^(NSError *error, Firebase *ref) {
handler(error, ref);
}];
这适用于第一次更新,但我第二次这样做时,所有现有的帖子都被删除了。但是,将代码更改为:
Firebase *baseRef = [[Firebase alloc] initWithUrl:@"https://tonightdb.firebaseio.com"];
NSString *usersPostsPath = [NSString stringWithFormat:@"users/%@/posts/%@/", userId, postId];
[baseRef updateChildValues:@{
usersPostsPath : postDescription,
// similar update path
}withCompletionBlock:^(NSError *error, Firebase *ref) {
handler(error, ref);
}];
正确更新 Firebase。
两者有什么区别?第一个怎么不行?
编辑
是否可以做到:
Firebase *baseRef = [[Firebase alloc] initWithUrl:@"https://<MY-APP>.firebaseio.com"];
NSString *newKey = [baseRef childByAutoId];
然后使用该键执行如下所示的更新:
[baseRef updateChildValues:@{
[NSString stringWithFormat:@"/posts/%@/", newKey] : // something
[NSString stringWithFormat:@"/posts/%@/members/<something>", newKey] : // something
withCompletionBlock:^(NSError *error, Firebase *ref) {
handler(error, ref, task);
}];
基本上是在同一个请求中对同一个路径发出多个更新,这在避免覆盖问题的同时事先不存在
您的第一个示例转换为更新说明:
"users/posts" = { "postid1": postDescription }
第二个例子翻译成:
"users/posts/postid1" = postDescription
作为一个计算机程序,Firebase 服务器对您提供的指令进行了相当字面的解释。它接受每条更新指令并将路径中的数据(=
之前的部分)替换为值(=
之后的部分)。
知道后,您可以看到在第二个示例中它将在 users/posts/postid1
处写入 postDescription
。这将替换该 post 的现有描述,但这可能是您想要的。
第二个例子在users/posts
写{ "postid1": postDescription }
。这将替换该位置的现有值,因此您实际上是用 new/updated 替换所有现有的 post。这可能不是您想要的。
更新
如果您正在创建一个新对象并将密钥散布到多个位置,您可以利用 childByAutoId
是纯客户端操作这一事实:
let newRef = ref.childByAutoId()
let newKey = newRef.key
ref.childByAppendingPath("child1").childByAppendingPath(newKey).setValue("one")
ref.childByAppendingPath("child2").childByAppendingPath(newKey).setValue("two")