更新 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")