Хороший способ заменить недопустимые символы в клавишах firebase?

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

Ошибка: недействительный ключ [email protected](не может содержать .$[]#)

Итак, по-видимому, я не могу индексировать информацию пользователя по электронной почте. Какова наилучшая практика для замены .?

У меня был успех смены . на -, но это не будет сокращено, так как в адресе есть адрес -.

В настоящее время я использую

var cleanEmail = email.replace('.','`');

но, скорее всего, будут конфликты с этим.

Ответы

Ответ 1

В адресе электронной почты замените точку . с запятой ,. Эта модель - лучшая практика.

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

У вас также есть другая проблема.

var cleanEmail = email.replace('.',','); // only replaces first dot

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

var cleanEmail = email.replace(/\./g, ','); // replaces all dots

Ответ 2

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

Мы обнаружили, что изменение формата хранения данных - лучший путь. Предположим, вам просто нужно сохранить одну вещь, имя пользователя.

[email protected]: "John Smith"

изменив его на

randomly_generated_node_name
   email:  "[email protected]"
   first:  "John"
   last:   "Smith"

Randomwise_generated_node_name - это строка, которую Firebase может генерировать с помощью childByAutoId, или действительно любой тип ссылки, которая не привязана непосредственно к данным.

Это дает большую гибкость: теперь вы можете изменить фамилию людей - скажите, женились ли они. Или измените их электронную почту. Вы можете добавить дочерний элемент "index" 0, 1, 2 и т.д., Который можно использовать для сортировки. Данные могут запрашиваться для любых дочерних данных. Все потому, что randomwise_generated_node_name является статической ссылкой на дочерние данные переменной в node.

Он также позволяет вам расширять данные в будущем без изменения существующих данных. Добавьте адрес, любимую еду, индекс для сортировки и т.д.

Изменить: запрос Firebase для электронной почты в ObjC:

//references all of the users ordered by email
FQuery *allUsers = [myUsersRef queryOrderedByChild:@"email"];

//ref the user with this email
FQuery *thisSpecificUser = [allUsers queryEqualToValue:@"[email protected]"]; 

//load the user with this email
[thisSpecificUser observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {
  //do something with this user
}];

Ответ 3

Я могу подумать о двух основных способах решения этой проблемы:

  • Функция кодирования/декодирования

Из-за ограниченного набора символов, разрешенных в ключе Firebase, решение состоит в том, чтобы преобразовать ключ в допустимый формат (encode). Затем выполните обратную функцию ( decode), чтобы преобразовать закодированный ключ обратно в качестве исходного ключа.

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

Предположим, вы хотите сохранить пользователей с помощью электронной почты в качестве ключа:

# path: /users/{email} is User;
/users/[email protected]: {
    name: "Alice",
    email: "[email protected]"
}

Приведенный выше пример не работает из-за точки в пути. Поэтому мы используем функцию encode для преобразования ключа в допустимый формат. [email protected] в шестнадцатеричном формате 616c69636540656d61696c2e636f6d, то:

# path: /users/{hex(email)} is User;
/users/616c69636540656d61696c2e636f6d: {
    name: "Alice",
    email: "[email protected]"
}

Любой клиент может получить доступ к этому ресурсу, если он имеет одну и ту же функцию hex.

Изменить: Base64 также может использоваться для кодирования/декодирования ключа. Может быть более эффективным, чем гексадецималы, но существует множество различных реализаций. Если клиенты не используют ту же самую реализацию, то они не будут работать должным образом.

Также могут использоваться специализированные функции (например, обрабатывающие только электронные письма). Но не забудьте обработать все случаи краев.

  1. Функция кодирования с сохраненным исходным ключом

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

Хорошей кодировкой для этого случая является алгоритм SHA-256. Это общий алгоритм с реализациями на многих платформах. И шансы столкновения очень тонкие.

Предыдущий пример с SHA-256 выглядит следующим образом:

# path: /users/{sha256(email)} is User;
/users/55bf4952e2308638427d0c28891b31b8cd3a88d1610b81f0a605da25fd9c351a: {
    name: "Alice",
    email: "[email protected]"
}

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

Ответ 4

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

public class HashingUtils {
    public HashingUtils() {
    }

    //generate 256 bits hash using SHA-256
    public String generateHashkeySHA_256(String email){
        String result = null;
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(email.getBytes("UTF-8"));
            return byteToHex(hash); // make it printable
        }catch(Exception ex) {
            ex.printStackTrace();
        }
        return result;
    }

    //generate 160bits hash using SHA-1
    public String generateHashkeySHA_1(String email){
        String result = null;
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-1");
            byte[] hash = digest.digest(email.getBytes("UTF-8"));
            return byteToHex(hash); // make it printable
        }catch(Exception ex) {
            ex.printStackTrace();
        }
        return result;
    }

    public String byteToHex(byte[] bytes) {
        Formatter formatter = new Formatter();
        for (byte b : bytes) {
            formatter.format("%02x", b);
        }
        String hex = formatter.toString();
        return hex;
    }
}

код для добавления пользователя в firebase

public void addUser(User user) {
    Log.d(TAG, "addUser: ");
    DatabaseReference userRef= database.getReference("User");

    if(!TextUtils.isEmpty(user.getEmailId())){
       String hashEmailId= hashingUtils.generateHashkeySHA_256(user.getEmailId());
        Log.d(TAG, "addUser: hashEmailId"+hashEmailId);
        userRef.child(hashEmailId).setValue(user);
    }
    else {
        Log.d(TAG,"addUser: empty emailId");
    }
}