Во-первых, пара ресурсов, если вы еще не сталкивались с ними:
EDIT: вы, очевидно, столкнулись с этими ресурсами, поскольку они указаны в вашем вопросе, но я бы посоветовал еще несколько раз перечитать руководство по структурированию данных.
Это подводит нас к вашему сценарию...
Два способа настройки данных на самом деле выполняют почти одно и то же!
Вы заметите, однако, что первый пример на самом деле указан как анти-шаблон в руководство "Структурирование данных".
- Выполнение этого вторым способом было бы полезно, если вы хотите загрузить данные пользователя, а затем задачи этого пользователя в другое время.
- The way you have it set up is fine if you only have one user accessing each todo list.
- For example, I do this in an app where I know that each user has one single location in a history list, and I only want to load the history of a user in certain scenarios.
/users/$userUid
дает мне данные пользователя, а /history/$userUid
дает мне историю пользователя.
- Это позволяет легко сегментировать нагрузку.
- Однако эта структура не дает никаких преимуществ, если списки дел используются разными пользователями и должны обновляться из нескольких источников.
- Если вам нужен общий доступ, вы на правильном пути и просто должны использовать ключи в качестве ссылок.
Другой подход:
- Вместо того, чтобы явно устанавливать объекты todo в
/todos/$uid
, вы можете отправить новый объект todo
в /todos
, чтобы он получил новый уникальный идентификатор (называемый ключом).
- Затем вы добавляете этот ключ к правильному
user
дочернему объекту todos
.
- Это позволит вам сначала загрузить данные пользователя и получить только индексы (ключи) задач, к которым принадлежит пользователь, и
- Затем вы можете независимо загрузить все те
todos
, к которым принадлежит пользователь.
Выполнение этого таким образом:
- Не позволяйте пользовательским объектам становиться огромными
- Разрешить нескольким пользователям обновлять один
todo
без необходимости обновлять его дочерние параметры в нескольких местах.
- Получите масштабируемые данные, разделив их на отдельные пути.
Вот последний пример данных из "Создание данных, которые Весы" раздела руководства: (с некоторыми комментариями, которые я добавил)
// An index to track Mary's memberships
{
"users": {
"mchen": {
"name": "Mary Chen",
// index Mary's groups in her profile
"groups": {
// the value here doesn't matter, just that the key exists
// these keys are used to figure out which groups should
// be loaded (at whatever appropriate time) for Mary,
// without having to load all the group's data initially (just the keys).
"alpha": true,
"charlie": true
}
},
...
},
// Here is /groups. In here, there would be a group with the key
// 'alpha' and another one with the key 'charlie'. Once Mary's
// data is loaded on the client, you would then proceed to load
// the groups from this list, since you know what keys to look for.
"groups": { ... }
}
Это обеспечивает более плоскую структуру.
Как говорится в документации,
да. Это необходимая избыточность для двусторонних отношений. Это позволяет нам быстро и эффективно получать сведения о членстве Мэри, даже когда список пользователей или групп исчисляется миллионами или когда правила безопасности и Firebase запрещают доступ к некоторым записям.
Итак, вопрос в том, как должны выглядеть ваши данные, чтобы пользователь мог иметь несколько списков дел, которыми можно было бы поделиться с другими пользователями?
Вот пример:
{
"users" : {
"google:1234567890" : {
"displayName" : "Username A",
"provider" : "google",
"provider_id" : "1234567890",
"todoLists" : {
"todoList1": true,
"todoList2": true
}
},
"google:0987654321" : {
"displayName" : "Username B",
"provider" : "google",
"provider_id" : "0987654321",
"todoLists" : {
"todoList2": true
}
}
},
"todoLists" : {
"todoList1" : {
// 'members' user for rules
"members" : {
"google:1234567890" : true
},
"records" : {
"rec_id1" : {
"todo" : "Walk the dog",
"createdAt" : "1426240376047"
},
"rec_id2" : {
"todo" : "Buy milk",
"createdAt" : "1426240376301"
},
"rec_id3" : {
"todo" : "Win a gold medal in the Olympics",
"createdAt" : "1426240376301"
}
}
},
"todoList2" : {
"members" : {
"google:1234567890" : true,
"google:0987654321" : true
},
"records" : {
"rec_id4" : {
"todo" : "Get present",
"createdAt" : "1426240388047"
},
"rec_id5" : {
"todo" : "Run a mile",
"createdAt" : "1426240399301"
},
"rec_id6" : {
"todo" : "Pet a cat",
"createdAt" : "1426240400301"
}
}
}
}
}
- В этом случае пользователь А загрузит оба списка, а пользователь Б загрузит только второй список. Если вы правильно настроите свои правила, все будет хорошо.
- При работе вы сначала загрузите данные пользователя, а затем загрузите каждый список задач в пользовательские списки задач из
/todoList
.
- Но на самом деле все это совершенно не нужно, если вы создаете приложение, в котором у одного пользователя есть один список задач с элементами задач, которые имеют только один контент.
- Side note, these "ids" should probably be a unique key, which can be accomplished using
Firebase.push()
.
В заключение все сводится к тому, как и когда вашему приложению нужны ваши данные, как часто данные обновляются и кем, а также к тому, чтобы свести к минимуму количество ненужных операций чтения и наблюдателей. Пространство обычно дешевое, операции (и наблюдатели) обычно нет.
И последнее, но не менее важное: правила и безопасность являются еще одним чрезвычайно важным фактором. В последней части руководства говорится:
«Таким образом, индекс быстрее и намного эффективнее. Позже, когда мы будем говорить о защите данных, эта структура также будет очень важна. Поскольку правила безопасности и Firebase не могут делать какие-либо «содержит» в списке дочерних узлов , мы будем широко использовать такие ключи».
Это рано, и я надеюсь, что не болтаю, но я столкнулся с теми же вопросами, когда впервые перешел от знания MySql к использованию неструктурированного, поэтому я надеюсь, что это поможет!
person
sbolel
schedule
13.03.2015