В вашей структуре временная таблица дублирует информацию о сообщениях, я думаю, что это не нормально для базы данных.

ользовал базу данных Firebase в реальном времени для моего тестового приложения для социальной сети, в котором вы можете просто следить и получать сообщения людей, на которых вы подписаны. Традиционная социальная сеть. Я структурировал свою базу данных примерно так:

Users
--USER_ID_1
----name
----email
--USER_ID_2
----name
----email

Posts
--POST_ID_1
----image
----userid
----date
--POST_ID_2
----image
----userid
----date

Timeline
--User_ID_1
----POST_ID_2
------date
----POST_ID_1
------date

У меня также есть другой узел «Контент», который просто содержит идентификатор всего поста пользователя. Таким образом, если «A» следует за «B», то все идентификаторы поста B, добавленные к временной шкале А. И если B опубликовал что-то, это также было добавлено во все сроки его подписчика.

Теперь это было мое решение для базы данных в реальном времени, но у нее явно есть некоторые проблемы с масштабируемостью

если у кого-то есть 10000 подписчиков, то новая запись будет добавлена ​​ко всей временной шкале 10000 подписчиков.Если у кого-то большое количество постов, то каждый новый подписчик получал все эти посты на своей временной шкале.

Это были некоторые из проблем.

Теперь я подумываю перенести всю эту штуку на пожарный, так как она была заявлена ​​как «Масштабируемая». Итак, как я должен структурировать свою базу данных так, чтобы проблемы, с которыми я сталкивался в базе данных в реальном времени, могли быть устранены в firestore.

 Tometoyou21 февр. 2018 г., 12:12
Вы решили это?
 Zicsus22 февр. 2018 г., 12:58
@tometoyou еще нет ..
 Zicsus18 нояб. 2017 г., 05:35
@jurgenBrandstetter Firestore прямо сейчас не поддерживает 'ИЛИ', и если это так, то и ваш метод не будет работать. Предположим, у кого-то 1000 подписчиков, чем у меня 1000 заявлений ИЛИ.
 Jürgen Brandstetter16 нояб. 2017 г., 12:21
Отказ от ответственности: я только готов через документацию пожарного магазина. Так как запросы к firestore намного лучше, чем к firebase-realtime-db, вам больше не нужно копировать данные. Итак, что бы я сделал: когда пользователь смотрит на свою временную шкалу, создайте запрос в firestore, который говоритgive me all posts which are from the people i follow, Что-то вроде: posts.where (пользователь == Джон ИЛИ пометить ИЛИ КАТИ ИЛИ ...). Я ожидаю, что что-то вроде этого работает. Если у меня будет время попробовать, я сообщу.
 Giovanny Piñeros18 мая 2018 г., 21:14
Я думал, может быть, если вы добавите в свой документ идентификатор человека, который следует за вами. Например, UserA следует за UserB, затем в пост-документе UserB вы вводите UserAID = true. Поэтому, когда вы делаете запрос, это будет что-то вроде == postDocRef.where (UserAID = true), но я не знаю, может ли документ в firestore поддерживать до n миллионов подписчиков

Ответы на вопрос(5)

и меня смущает, почему предлагаемая реализация наhttps://firebase.google.com/docs/database/android/structure-data#fanout не будет работать в вашем случае. Что-то вроде этого:

users
--userid(somedude)
---name
---etc
---leaders: 
----someotherdude
----someotherotherdude

leaders:
--userid(someotherdude)
---datelastupdated
---followers
----somedude
----thatotherdude
---posts
----postid

posts
--postid
---date
---image
---contentid

postcontent
--contentid
---content

Далее в руководстве упоминается: «Это необходимая избыточность для двусторонних отношений. Она позволяет вам быстро и эффективно получать членство в Ada, даже если список пользователей или групп масштабируется до миллионов». эта масштабируемость исключительно для Firestore.

Если я не пропускаю что-то, главная проблема, похоже, заключается в существовании самого узла временной шкалы. Я понимаю, что это облегчает создание представления о временной шкале конкретного пользователя, но это происходит за счет необходимости поддерживать все эти отношения и значительно задерживает ваш проект. Является ли слишком неэффективным использование запросов для построения временной шкалы на лету из структуры, аналогичной приведенной выше, на основе представленного пользователя?

Пользователи в вашем приложении имеют небольшое количество подписчиков.

Пользователи в вашем приложении имеют большое количество подписчиков. Если мы собираемся хранить целых последователей в одном массиве в одном документе в FireStore. Тогда он достигнет лимита пожарного хранилища в 1 MiB за документ.

В первой ситуации каждый пользователь должен хранить документ, в котором список подписчиков хранится в одном документе в одном массиве. ИспользуяarrayUnion() а такжеarrayRemove() можно эффективно управлять списком подписчиков. И когда вы собираетесь опубликовать что-то в вашей временной шкале, вы должны добавить список подписчиков в почтовый документ.

И используйте запрос, указанный ниже, чтобы получить сообщения

postCollectionRef.whereArrayContains("followers", userUid).orderBy("date");

Во второй ситуации вам просто нужно разбить пользователя на следующий документ на основе размера или количества массивов подписчиков. После достижения размера массива до фиксированного размера идентификатор следующего последователя должен быть добавлен в следующий документ. И первый документ должен содержать поле hasNext, в котором хранится логическое значение. При добавлении нового сообщения вы должны дублировать почтовый документ, и каждый документ состоит из списка подписчиков, который разрывается ранее. И мы можем сделать тот же запрос, который приведен выше, для получения документов.

Вам необходимо поддерживать отношения между подписчиками:

Followers
-leading_id
-follower_id
-created_at

Далее, я думаю, вам не нужна временная таблица. Когда вы откроете ленту новостей, получите всех подписчиков и присоединитесь к их сообщениям, плюс вы можете использовать какой-то порядок и фильтровать запрос.

В вашей структуре временная таблица дублирует информацию о сообщениях, я думаю, что это не нормально для базы данных.

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

Я думаю о схеме, которая имеет три коллекции верхнего уровня дляusers, users that a user is following а такжеposts.

Firestore-root
   |
   --- users (collection)
   |     |
   |     --- uid (documents)
   |          |
   |          --- name: "User Name"
   |          |
   |          --- email: "[email protected]"
   |
   --- following (collection)
   |      |
   |      --- uid (document)
   |           |
   |           --- userFollowing (collection)
   |                 |
   |                 --- uid (documents)
   |                 |
   |                 --- uid (documents)
   |
   --- posts (collection)
         |
         --- uid (documents)
              |
              --- userPosts (collection)
                    |
                    --- postId (documents)
                    |     |
                    |     --- title: "Post Title"
                    |     |
                    |     --- date: September 03, 2018 at 6:16:58 PM UTC+3
                    |
                    --- postId (documents)
                          |
                          --- title: "Post Title"
                          |
                          --- date: September 03, 2018 at 6:16:58 PM UTC+3

если у кого-то есть 10000 подписчиков, то новая запись будет добавлена ​​ко всей временной шкале 10000 подписчиков.

Это не будет проблемой, потому что именно по этой причине коллекции хранятся в Firestore. Согласно официальной документациимоделирование базы данных Cloud Firestore:

Облачный Firestore оптимизирован для хранения больших коллекций небольших документов.

Вот почему я добавилuserFollowing как коллекция, а не как простой объект / карта, которая может содержать другие объекты. Помните, максимальный размер документа в соответствии с официальной документацией относительнолимиты и квота является1 MiB (1,048,576 bytes), В случае сбора, нет никаких ограничений в отношении количества документов под коллекцией. Фактически, для такого рода структур оптимизирован Firestore.

Таким образом, имея эти 10000 подписчиков таким образом, будет работать отлично. Кроме того, вы можете запросить базу данных таким образом, что вам не нужно будет что-либо копировать.

Как видите, база данных в значительной степениденормализованной что позволяет вам сделать запрос очень просто. Давайте рассмотрим пример, но прежде чем создавать соединение с базой данных и получитьuid пользователя, использующего следующие строки кода:

FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();

Если вы хотите запросить базу данных, чтобы получить всех пользователей, за которыми следит пользователь, вы можете использоватьget() позвоните по следующей ссылке:

CollectionReference userFollowingRef = rootRef.collection("following/" + uid + "/userFollowing");

Таким образом, вы можете получить все объекты пользователя, за которыми следит пользователь. Имея их, вы можете просто получить все свои сообщения.

Допустим, вы хотите добавить в свою хронологию последние три сообщения каждого пользователя. Ключом к решению этой проблемы при использовании очень больших наборов данных является загрузка данных небольшими порциями. Я объяснил в своем ответе от этогоПочта рекомендуемый способ разбивать запросы на страницы, комбинируя курсоры запросов сlimit() метод. Я также рекомендую вам взглянуть на этовидео для лучшего понимания. Таким образом, чтобы получить последние три сообщения от каждого пользователя, вы должны рассмотреть возможность использования этого решения. Итак, сначала вам нужно получить первые 15 пользовательских объектов, за которыми вы следите, а затем на основе ихuid, чтобы получить свои последние три поста. Чтобы получить последние три сообщения одного пользователя, используйте следующий запрос:

Query query = rootRef.collection("posts/" + uid + "/userPosts").orderBy("date", Query.Direction.DESCENDING)).limit(3);

По мере прокрутки вниз загружайте другие 15 пользовательских объектов и получайте их последние три сообщения и так далее. Заdate Вы также можете добавить другие свойства к вашемуpost объект, как количество лайков, комментариев, акций и так далее.

Если у кого-то большое количество постов, то каждый новый подписчик получал все эти посты на своей временной шкале.

Ни за что. Нет необходимости делать что-то подобное. Я уже объяснил выше, почему.

 ivancoene18 мар. 2019 г., 14:56
@ AlexMamo Я думаю, я могу жить с вашим решением, спасибо :)
 tccpg28818 нояб. 2018 г., 13:51
По сути, я пытаюсь выяснить, как документы записываются в узел «userfollowing». Допустим, подписаться на кого-то, кто имеет 10000 предыдущих сообщений. Как эти сообщения записываются в мой пользовательский следующий узел?
 Alex Mamo06 дек. 2018 г., 09:26
@BrendanMcGill Спасибо, Брендан. Нет, в этом конкретном случае вы должны добавить новую коллекцию, которая будет содержать все сообщения всех пользователей. Firstore не разрешает запросы по нескольким коллекциям. Если вы считаете, что мой ответ оказался полезным, рассмотрите возможность голосования. Буду признателен. Спасибо!
 Alex Mamo18 нояб. 2018 г., 11:16
@ tccpg288 Я не уверен, что понимаю, о чем ты спрашиваешь, но это звучит как еще один вопрос. Я посмотрю на ваш новый вопрос и, если узнаю ответ, напишу его вам. В связи с этим, пожалуйста, оставьте еще один свежий вопрос с дополнительной информацией, чтобы я и другие пользователи могли вам помочь.
 tccpg28817 нояб. 2018 г., 20:12
Очень интересный ответ. Я нахожусь в аналогичной ситуации, пытаясь организовать свои данные как можно более экономичными:stackoverflow.com/questions/53347695/..., Что я не понимаю с вашей стороны, если клиент решает следовать за пользователем, как вы записываете все данные этого последовавшего пользователя в «следующий» узел в этой структуре?

Хорошее решение.Почему?


Теперь давайте перейдем к теме. Как вы уже указали, у вашего решения есть некоторые недостатки. Вот два, которые я мог понять.

Это тратит впустую различные виды ресурсов в очень большом количестве. К ним относятся квота данных, хранение в облаке, системная память и мощность процессора.Вопросы, связанные с организацией постов в хронологическом порядке.

Решения - это полная модернизация вашей базы данных и использование другого метода для извлечения данных соответственно.


Редизайн базы данных

Избегайте дублирования данных полностью. Вот хороший пример структуры базы данных для социальных сетей.

-root
    -users
        -0001
            -name:"name"
            -profile_image:"https://www.example.com/profileimages/profileimage"
            -followings:"002, 003"
            -posts
                -0001
                    -timestamp:"1535650853"
                    -title:"title"
                    -content: "This is a dummy content"
                    -media: "https://www.example.com/medias/media"
                -0002
                    -timestamp:"1535650853"
                    -title:"title"
                    -content: "This is a dummy content"
                    -media: "https://www.example.com/medias/media"
        -0002
            -name:"name"
            -profile_image:"https://www.example.com/profileimages/profileimage"
            -posts
                -0001
                    -timestamp:"1535650853"
                    -title:"title"
                    -content: "This is a dummy content"
                    -media: "https://www.example.com/medias/media"
        -0003
            -name:"name"
            -profile_image:"https://www.example.com/profileimages/profileimage"
            -followings:"001"


Как получить сообщения

Поскольку вам нужно получать сообщения из разных мест, вам нужно сделать что-то вроде этого.

step 1 : Get a list of UIDs of all following users
step 2 : Take first UID
step 3 : Get all post with the UID and add to list of posts
step 4 : If next UID exists do step 3 with it
step 5 : Sort all according to the timestamp

В случае, если вам нужна нумерация страниц, вы можете пойти, даже решение проблемы осложнений. Очевидно, это приводит к значительному улучшению производительности.

step 1 : Get a list of UIDs of all following users
step 2 : Take first UID
step 3 : Get the latest post with the UID (using orderByChild(), limitToLast()) and add to a priority queue in appropriate position.If no element exists, skip the step.
         (A priority queue means an array in of elements which is about to be added to the resultant array. It should be sorted in such a way that the first element can be the next element in the resultant array.)
step 4 : If next UID exists do step 3 with it. Other wise, it means One cycle completed. Go to next step in that case.
step 5 : If limit is not exceeded, get the top element from the queue and add it to resultant array. Then remove from the priority queue. Stop otherwise.
step 6 : Get the next element from the array and add to the priority queue in appropriate position. If no element exists, skip the step.
step 7 : Go to step 5
 Anees07 нояб. 2018 г., 05:37
Взгляни наэто Почта
 tccpg28818 нояб. 2018 г., 17:33
Можете ли вы применить свою логику к моему сценарию здесь?stackoverflow.com/questions/53347695/...
 Purus07 нояб. 2018 г., 06:08
Вышеупомянутый пост предлагает не структурировать данные, как вы упомянули. есть идеи?
 Purus07 нояб. 2018 г., 05:28
С этим дизайном, как все последние сообщения могут быть восстановлены? Я имею в виду, чтобы напрямую запросить в коллекции "сообщений" ..
 Anees07 нояб. 2018 г., 06:26
Вы можете структурировать базу данных, как я описал. Для запроса вы можете использовать метод, описанный в упомянутом посте.

Ваш ответ на вопрос