У меня есть 2 узла в моей базе данных items
и my_items
.
У меня есть эта функция, которая выполняет multi-path update
, эта функция удаляет элемент из items
и добавляет его в my_items
пользователя:
Я защитил узел my_items
таким образом, что вы можете писать в него только в том случае, если элемент существует в items
, в противном случае он не работает:
private void getItem(String uid, String item_key) {
Map<String, Object> updates = new HashMap<>();
//delete item
updates.put("items/" + item_key, null);
//give the item to the user
updates.put("my_items/" + uid + "/" + item_key, itemObject);
mDatabaseReference.updateChildren(updates);
}
Если пользователи A, B, C, D одновременно вызвали функцию getItem(..)
для одного и того же item id
:
Имеет ли это смысл:
Succeeds
(теперь предмет удален из items
и добавлен пользователю А в my_items
)
Fails
(потому что предмет больше не существует в items
, поэтому правило безопасности my_items
предотвращает это)
Fails
(та же самая причина)
Fails
(та же самая причина)
Это то, что произошло бы? Или я понял это неправильно?
Спасибо.
Вы можете... сделать это в одном атомарном обновлении для обоих мест:
JavaScript
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com"); // Generate a new push ID for the new post var newPostRef = ref.child("posts").push(); var newPostKey = newPostRef.key(); // Create the data we want to update var updatedUserData = {}; updatedUserData["user/posts/" + newPostKey] = true; updatedUserData["posts/" + newPostKey] = { title: "New Post", content: "Here is my new post!" }; // Do a deep-path update ref.update(updatedUserData, function(error) { if (error) { console.info("Error updating data:", error); } });
Джава
Firebase ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com"); // Generate a new push ID for the new post Firebase newPostRef = ref.child("posts").push(); String newPostKey = newPostRef.getKey(); // Create the data we want to update Map newPost = new HashMap(); newPost.put("title", "New Post"); newPost.put("content", "Here is my new post!"); Map updatedUserData = new HashMap(); updatedUserData.put("users/posts/" + newPostKey, true); updatedUserData.put("posts/" + newPostKey, newPost); // Do a deep-path update ref.updateChildren(updatedUserData, new Firebase.CompletionListener() { @Override public void onComplete(FirebaseError firebaseError, Firebase firebase) { if (firebaseError != null) { System.out.println("Error updating data: " + firebaseError.getMessage()); } } });
Цель-C
Firebase *ref = [[Firebase alloc] initWithUrl: @"https://<YOUR-FIREBASE-APP>.firebaseio.com"]; // Generate a new push ID for the new post Firebase *newPostRef = [[ref childByAppendingPath:@"posts"] childByAutoId]; NSString *newPostKey = newPostRef.key; NSString *updateUserPath = [NSString stringWithFormat:@"users/posts/%@", newPostKey]; NSString *updatePostPath = [NSString stringWithFormat:@"posts/%@", newPostKey]; // Create the data we want to update NSMutableDictionary *updatedUserData = [[NSMutableDictionary alloc] init]; [updatedUserData setValue:[NSNumber numberWithBool:YES] forKey:updateUserPath]; [updatedUserData setValue:@{@"title": @"New Post", @"content": @"Here is my new post!"} forKey:updatePostPath]; // Do a deep-path update [ref updateChildValues:updatedUserData withCompletionBlock:^(NSError *error, Firebase *ref) { if (error) { NSLog(@"Error updating data: %@", error.debugDescription); } }];
Быстрый
"https://<YOUR-FIREBASE-APP>.firebaseio.com") // Generate a new push ID for the new post let newPostRef = ref.childByAppendingPath("posts").childByAutoId() let newPostKey = newPostRef.key // Create the data we want to update let updatedUserData = ["users/posts/(newPostKey)": true, "posts/(newPostKey)": > ["title": "New Post", "content": "Here is my new post!"]] // Do a deep-path update ref.updateChildValues(updatedUserData, withCompletionBlock: { (error, ref) -> > Void in if (error) { print("Error updating data: (error.description)") } })
Обновления глубокого пути позволяют писать более чистый код и легко денормализировать данные на нескольких узлах в вашей базе данных Firebase.
База данных Firebase Realtime обрабатывает (записывает) операции последовательно. Таким образом, любая предыдущая операция записи будет завершена до того, как будет обработана следующая. Это означает, что любые данные, записанные предыдущим пользователем, действительно будут присутствовать в переменной root
при оценке правил безопасности для последующих операций записи.
Большое спасибо, я понял, что вы сказали. Итак, согласно моей приведенной выше теории, верно ли, что независимо от того, сколько пользователей вызвали функцию, только один должен добиться успеха, а другие должны потерпеть неудачу?
Это может зависеть от того, как вы реализуете правила. Я не хочу давать одеяло «ваш подход будет работать 👍» в абстрактном описании, следовательно, объясняя, как работает система. Изолированные многопользовательские операции определенно могут быть реализованы с транзакциями и/или обновлениями с несколькими путями и правилами безопасности, поэтому, если у вас возникнут проблемы, я рекомендую опубликовать новый вопрос с MCVE, и мы можем посмотреть.
Спасибо Фрэнк за вашу помощь и за ваше время. Вскоре я спрошу, какое правило безопасности для items
и my_items
будет лучшим для достижения этой теории. Надеюсь, вы это проверите.
Мой вопрос не в том, как выполнить обновление с несколькими путями. Я просто хочу знать, имеет ли смысл приведенный выше пример с учетом правила безопасности, которое я написал