Я изучал базу данных Firebase для Android и понял, что он сохраняет свои данные следующим образом:
Я не очень хорошо знаком с методами NoSQL и пытаюсь понять, почему мы должны упорствовать каждый объект post
дважды - в posts
и user_posts
соответственно. В документации говорится, что этот подход называется "Fan Out", и я полностью согласен с тем, что было бы полезно получить доступ к сообщениям пользователей через простую конструкцию типа databaseReference.child("user-posts").child("<user_uid>")
. Но зачем нам нужен posts
node? Что делать, если нам нужно обновить некоторые сообщения - мы должны сделать это дважды?
// [START write_fan_out]
private void writeNewPost(String userId, String username, String title, String body) {
// Create new post at /user-posts/$userid/$postid and at
// /posts/$postid simultaneously
String key = mDatabase.child("posts").push().getKey();
Post post = new Post(userId, username, title, body);
Map<String, Object> postValues = post.toMap();
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put("/posts/" + key, postValues);
childUpdates.put("/user-posts/" + userId + "/" + key, postValues);
mDatabase.updateChildren(childUpdates);
}
// [END write_fan_out]
Итак, мне интересно... когда этот подход может быть полезен, а когда нет? Предоставляет ли Firebase SDK какие-либо инструменты для синхронизации всех дубликатов при обновлении или удалении данных?
ОБНОВЛЕНИЕ: Вот объяснение получено от команды Firebase:
причина дублирования сообщений - это то, что мы хотим иметь возможность быстро получить все сообщения, принадлежащие пользователю (как вы сказали), и фильтрация из списка всех сообщений, когда-либо получавших сообщения от одного пользователя может стать довольно дорогостоящим по мере расширения количества сообщений.
Это означает, что мы должны обновить сообщение в двух местах когда мы его обновляем. Это делает код немного уродливым, но поскольку запросы более распространены, чем лучше писать для оптимизации чтение данных.
Я подозреваю, что этот подход может выглядеть не совсем изящным, но, вероятно, это самый быстрый вариант для больших наборов данных, если вы выполняете SELECT чаще, чем UPDATE. Однако в некоторых случаях я предпочел бы использовать другие рекомендуемые здесь решения.