База данных Firebase – техника «Fan Out»

Я изучал образец базы данных Firebase для Android и понял, что он хранит свои данные следующим образом:

Введите описание изображения здесь

Я не очень хорошо знаком с методами NoSQL и пытаюсь понять, почему мы должны упорствовать каждый объект сообщения дважды – на posts и user_posts соответственно. В документации говорится, что этот подход называется «Fan Out», и я полностью согласен с тем, что было бы полезно получить доступ к сообщениям пользователя через простую конструкцию, такую ​​как databaseReference.child("user-posts").child("<user_uid>") . Но зачем нам нужен узел posts ? Что делать, если нам нужно обновить некоторые сообщения, мы должны сделать это дважды?

 // [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. Однако в некоторых случаях я предпочитаю придерживаться других решений, рекомендованных здесь.

Solutions Collecting From Web of "База данных Firebase – техника «Fan Out»"

Data Fan Out – отличная техника для управления огромными объемами данных . Если вы не используете этот шаблон, у вас могут возникнуть серьезные проблемы масштабирования в будущем.

Что я вижу из вашей структуры базы данных, так это то, что вы дважды храните всю информацию о почте , и это не очень хорошая практика. Вместо этого вы хотите сохранить только ссылку на сообщение под другим узлом. Таким образом, у вас будет узел с именем users-posts который будет состоять из пользовательских ключей, и каждый из этих ключей будет иметь набор ключей сообщений со значением true . Чтобы сделать это более понятным:

Введите описание изображения здесь

Таким образом, вы отслеживаете, какие записи пользователь написал в узле users-posts ; А также пользователь, который написал каждое сообщение под узлом posts . Теперь вам может понадобиться получить список сообщений всех пользователей. То, что вам нужно будет сделать, это синхронизировать на users-posts/USER_KEY/ чтобы получить ключи для всех сообщений, которые был написан пользователем, а затем получить дополнительную информацию о сообщениях, используя только что полученный ключ сообщения .

Почему этот дизайн базы данных рекомендуется? Поскольку вы получаете гораздо меньше информации для каждой синхронизации (с Firebase мы не выдаем запросы per se, поэтому я называю чтение синхронизацией). В вашем примере, если вы присоедините слушателя к user-posts/USER_KEY/ чтобы получить список всех сообщений, вы также попросите ВСЕ информацию о КАЖДОМ И КАЖДОМ сообщении, которое они написали. При использовании подхода к отключению данных вы можете просто запросить необходимую информацию, потому что у вас уже есть ключ от сообщений.

На мой взгляд, это не очень хороший подход, так как вам нужно синхронизировать эти данные, и Firebase не предоставляет никаких инструментов для синхронизации дубликатов. Хорошим подходом было бы хранить только ключ в user-posts .

Я предлагаю прочитать это, очень интересно понять, как структурировать данные: https://www.firebase.com/docs/web/guide/structuring-data.html