Структура данных JSON, приводящая к наименьшему количеству переданных данных из базы данных

Я пытаюсь понять, как я могу структурировать определенный набор данных, используя объект JSON.

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

 {
     0--{name:"Dog", details:{somestuffhere}}
     |
     1--{name:"Cat", details:{somestuffhere}}
     |
     2--{name:"Cow", details:{somestuffhere}}
    ...
 }

используя firebase, я могу посмотреть ТОЛЬКО запись имени для Dog, используя /0/name

Насколько я понимаю, когда я звоню в firebase (я использую angularjs), он передает весь объект JSON. Это отлично работает для небольших наборов данных, но предположим, что набор данных увеличивается даже до 5 МБ. Первоначальная загрузка очень медленная (на мой взгляд), но затем все может быть не так уж плохо (хотя вы просто держитесь за большое количество данных, с которыми можно поиграть).

Я пытаюсь придумать способ структурировать свои данные, поэтому, если я хочу получить ТОЛЬКО список имен, я вытаскиваю детали в зависимости от имени (например, если пользователь щелкает).

В идеале я бы назвал /name, и он вернул бы ТОЛЬКО все имена (а не оставшиеся связанные данные).

У кого-нибудь есть предложения?

РЕДАКТИРОВАТЬ: в качестве примера я использовал Dog Cat Cow, на самом деле это люди, и приложение может добавить имя и подробности (на других страницах). Я хотел бы сначала увидеть список имен, а затем щелкнуть их как ссылку, если она существует, если имя не существует, я создам его, а затем разрешить добавление «подробностей». Я надеюсь, что это поможет больше. (Я предполагаю, что база данных всегда будет расти, поэтому я сказал 5 МБ, на самом деле она может вырасти до гораздо большего, но я не знаю, это зависит от использования)


person onaclov2000    schedule 10.12.2013    source источник
comment
довольно трудно для любого здесь переварить Dog/Cat/Cow и somestuffhere и превратить это в совет о том, как структурировать доставку 5 МБ данных для приложения, о котором они ничего не знают.   -  person charlietfl    schedule 10.12.2013
comment
Вам, конечно, нужна настоящая база данных.   -  person Hot Licks    schedule 10.12.2013
comment
На самом деле вы должны согласиться, если вы ожидаете, что БД вырастет где-то в диапазоне МБ, и ожидаете, что ваши пользователи будут потенциально нетерпеливы или не захотят ждать синхронизации данных для удобства получения всех данных и возможности отключения от сеть, то вы должны просто использовать обычную базу данных и передавать нужные вам данные.   -  person shaunhusain    schedule 10.12.2013
comment
Я еще не использовал firebase, но, основываясь на небольшом быстром исследовании, кажется, что он полагается на синхронизацию данных между клиентами, поэтому я предполагаю, что это означает, что при первой загрузке на устройство оно каким-то образом кэшируется, а затем изменения, вероятно, дифф.   -  person shaunhusain    schedule 10.12.2013
comment
@Hot Licks - что не так с поддельными базами данных? Или вы имели в виду реляционную базу данных?   -  person JeffO    schedule 14.12.2013


Ответы (1)


Структура данных

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

{
 "names": 
    {
      "Dog": 0,
      "Cat": 1,
      "Cow": 2
    },
 "animals": 
    {
       0: {name:"Dog", details:{somestuffhere}},
       1: {name:"Cat", details:{somestuffhere}},
       2: {name:"Cow", details:{somestuffhere}}
    }
}

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

Когда вы добавляете новое животное, не забудьте также добавить соответствующую запись /names.

Использование этой структуры с AngularJS

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

Этот первый AngularFire загружает наш список имен.

// Load the list of names to $scope.names
angularFire(new Firebase("http://[Your Firebase].firebaseio.com/names"), $scope, "names"));

Затем, когда пользователь выбирает животное, используется новый AngularFire для пути /names/{Animal} для динамической загрузки сведений об этом животном. В этом примере предполагается, что уникальный ключ животного хранится в переменной animalKey.

// Load the specific animal details to $scope.animal
angularFire(new Firebase("http://[Your Firebase].firebaseio.com/animals/").child(animalKey), $scope, "animal"));

Теперь данные о нашем животном выставлены на $scope.animal, и мы не загрузили все ненужные данные о других животных.

Безопасное добавление новых животных

Ответ на комментарий к этому ответу

Общий совет: никогда не используйте увеличивающиеся целые числа в качестве ключей в Firebase. Из-за того, что Firebase работает в режиме реального времени, вероятность того, что два пользователя одновременно добавят новый элемент с одним и тем же увеличенным целочисленным ключом (в данном случае 3), очень высока, что приведет к перезаписи одной из их записей. . Вместо этого используйте .push() Firebase.

В вашем сценарии вы должны обойти AngularFire и использовать .push в ссылке Firebase. Попробуй это:

var newAnimalRef = (new Firebase('http://[Your Firebase].firebaseio.com'))
    .child('animals')
    .push({name: 'Fish', details: ""});

Он создаст новый дочерний элемент /animals с таким ключом, как -fj213jjkaisdja. Затем мы можем использовать .once, чтобы добавить новый элемент в индекс /names:

newAnimalRef.once('value', function (snapshot) { 
    (new Firebase('http://[Your Firebase].firebaseio.com'))
        .child('names')
        .child(snapshot.val().name)
        .set(snapshot.name()) 
});

Затем бум, мы добавили ребенка чистым и безопасным способом.

Заключительные примечания

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

  2. Будьте осторожны при потенциальном создании нескольких AngularFires, связанных с одним и тем же полем в $scope. Если вы не будете осторожны, вы можете закончить тем, что изменения в одном поле будут записаны в несколько путей в Firebase. Чтобы предотвратить это, либо привяжите AngularFire только к $scope, который будет регулярно отключаться (т. е. к контроллеру, специфичному для модуля, отображающего данные о животных), либо используйте метод disassociate, переданный в разрешенное обещание из AngularFire, как я делаю в другой мой ответ.

person Abe Haskins    schedule 10.12.2013
comment
в ответ на № 3, как мне сопоставить имя животного с числом, как в приведенном примере, сохраняя при этом характер в реальном времени? Отличный ответ, и пока я размышлял над ним всю ночь, я пришел к такому же выводу. - person onaclov2000; 10.12.2013
comment
Обновлен мой ответ с лучшим объяснением. - person Abe Haskins; 11.12.2013