Запрашивайте пользователей по имени или адресу электронной почты с помощью Firebase (Swift)

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

  1. Запросите моих пользователей и найдите только тех, которые содержат определенную строку в своем имени (или адресе электронной почты), и добавьте их в массив.
  2. Получите всех моих пользователей и добавьте их в массив.

Соответствующая часть моих данных для этого вопроса выглядит так: введите здесь описание изображения

Как видите, я использую простой логин Firebase (позже я хотел бы также добавить логин Facebook) и сохраняю своих пользователей по их uid.

Часть моего файла правил выглядит так:

"registered_users": {
    ".read": true,
    ".write": true,
    ".indexOn": ["name"]
 }

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

Я также прочитал часть «Получение данных» в руководстве Firebase iOS на их веб-сайте, и, согласно этому руководству, мой код для получения всех имен пользователей и адресов электронной почты должен работать, по крайней мере, я так думаю. Но это не так. Вот мой код:

func getUsersFromFirebase() {
        let registeredUserRef = firebaseRef.childByAppendingPath("registered_users")
        registeredUserRef.queryOrderedByChild("name").observeSingleEventOfType(.Value, withBlock: { snapshot in
            if let email = snapshot.value["email"] as? String {
                println("\(snapshot.key) has Email: \(email)")
            }
            if let name = snapshot.value["name"] as? String {
                println("\(snapshot.key) has Name: \(name)")
            }
        })
    }

Я заметил, что в руководстве по firebase всегда использовался тип ChildAdded, а не Value, но для меня Value имеет больше смысла. Вывод с Value — это ничего, а вывод с ChildAdded — это только один пользователь, а именно тот, который вошел в систему прямо сейчас.

Итак, мои вопросы:

  1. Могу ли я выполнить этот запрос с моей текущей структурой данных или мне нужно избавиться от истории пользователей по их uid?
  2. Если да, то как мне изменить свой код, чтобы он работал?
  3. Если нет, то как лучше всего хранить моих пользователей и сделать возможным запрос их по имени?
  4. Как я могу запросить, например. "собрать" и получить только пользователя simplelogin:1 (Макс Мустерманн)?

Надеюсь, мое описание достаточно подробное. Заранее спасибо за вашу помощь.

Дополнение:

Странно то, что в руководстве «Получение данных» говорится, что возможен запрос и сортировка следующих данных по высоте.

Данные:

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

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

И разве это не то же самое, что я намереваюсь сделать?


person X.X_Mass_Developer    schedule 16.03.2015    source источник
comment
Как мы можем сохранить данные, как вы сохранили?   -  person Devang Goswami    schedule 28.07.2015


Ответы (2)


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

https://groups.google.com/d/msg/firebase-talk/Wgaf-OIc79o/avhmN97UgP4J

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

Во-вторых, вам нужно сгладить ваши данные, если вы хотите сделать запрос, так как запрос идет только на один уровень (не может запрашивать данные в дочерних заметках)

Наконец, если вы не хотите сглаживать свои данные, один концептуальный вариант ответа на ваш вопрос;

  1. Если возможно, ObserveSingleEventOfType:FEventTypeValue на узле зарегистрированных пользователей. Это приведет к считыванию всех зарегистрированных пользователей в моментальный снимок.
  2. Итерация по снимку и чтение каждого пользователя в массив (как объекты словаря)
  3. Затем используйте NSPredicate для извлечения нужного массива пользователей.

Я провел множество тестов и с точки зрения производительности, это незначительно, если у вас нет тысяч пользователей.

Надеюсь, это поможет!

person Jay    schedule 17.03.2015
comment
Спасибо за ваш ответ. Но не могли бы вы еще раз взглянуть на мой вопрос, потому что я кое-что добавил в конце. - person X.X_Mass_Developer; 25.03.2015
comment
И еще, было бы неплохо добавить еще одну запись в мою базу данных, в которой хранятся имена всех пользователей на первом уровне (чтобы иметь возможность запрашивать его) и идентификатор на втором уровне. Таким образом, я мог бы найти Макса Мустерманна в базе данных имен, получить его идентификатор оттуда и получить остальные его данные в базе данных register_users, запросив его идентификатор. Или это будет слишком много накладных расходов? Проблема, конечно, в том, что я не смогу также искать адреса электронной почты, если не создам еще одну запись в базе данных с адресами электронной почты. И это не может быть хорошо, верно? - person X.X_Mass_Developer; 25.03.2015
comment
В вашем фрагменте кода getUsersFromFirebase: FEEventTypeValue считывает весь узел данных за один раз в один снимок. Затем вы несете ответственность за повторение этого снимка и извлечение нужных данных. Таким образом, внутри блока вы захотите использовать встроенную функциональность ( FDataSnapshot *child в snapshot.children ) {} для получения каждого дочернего элемента. - person Jay; 26.03.2015
comment
Value Event & Child Added делают две разные вещи. Событие value описано в комментарии выше. Добавленное событие Child делает две вещи: 1) Оно читает в каждом дочернем элементе в узле, по одному, выполняя код в блоке один раз для каждого дочернего элемента - это дает вам возможность сказать... читать исходные данные для NSTableView. 2) Затем он ожидает добавления дочернего элемента, и когда это происходит, блок выполняется. - person Jay; 26.03.2015

Чтобы ответить на ваши вопросы

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

2) Если да, то как мне изменить свой код, чтобы он работал?

Вот быстрый пример, который запрашивает по фамилии пользователя:

Firebase *usersNodeRef = your users node 'registered_users'
FQuery *allUsersRef = [usersNodeRef queryOrderedByChild:@"lastName"];
FQuery *specificUserRef = [allUsers queryEqualToValue:@"aLastName"];

[specificUser observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {

  NSDictionary *dict = snapshot.value;
  NSString *key = snapshot.key;

  NSLog(@"key = %@ for child %@", key, dict);

}];

Как я могу запросить, например. "собрать" и получить только пользователя simplelogin:1 (Макс Мустерманн)?

В вашей структуре узла use пользователи хранятся в узлах с ключом. Ключом является simplelogin: 1 и т. д. snapshot.key покажет это. Так что это сделка пары ключ/значение...

значение = снимок.значение ключ = снимок.ключ

person Jay    schedule 26.03.2015