2016-07-10 2 views
3

Я только что пришел из школы реляционных баз данных и работа с базами данных JSON - непростая задача для новых пользователей. У меня есть эта структура для хранения пользователей:Продвинутый запрос Firebase с фильтром в Swift

{ 
    "users" : { 
    "0CcKvNkOm5fVqL" : { 
     "birthday" : 564688000, 
     "country" : "US", 
     "email" : "[email protected]", 
     "firstName" : "John", 
     "gender" : "male", 
     "isOnline" : true, 
     "lastLoginDate" : 1468166460486, 
     "lastName" : "Paul", 
     "learningLanguages" : [ { 
     "language" : "fr_FR", 
     "levelID" : 2 
     } ], 
     "profileImage" : "https://firebasestorage.googleapis.com/image.jpg", 
     "providerID" : "Firebase", 
     "registrationDate" : 1468168460486, 
     "speakingLanguages" : [ { 
     "language" : "es_ES", 
     "levelID" : 7 
     } ] 
    } 
    } 
} 

я предлагаю экран поиска в мое приложение, где пользователи могут искать других пользователей, и они могут объединить все эти параметры фильтра:

Пример:

Получить 10 пользователи starting from index 0, которые:

  • male
  • и от "US"
  • иspeaks "da_DK" с levelID 2или/и"fr_FR" с any level
  • и узнает "de_DE" with уровень 1 **and/or** узнает "ar_AR" with уровень 4`
  • и с age range between 18 and 24
  • и порядковый номер isOnlineиlast login date.

Это легкая задача с SQL, если предположить, что есть таблица называется users_languages:

SELECT ... 
FROM users AS u 
JOIN users_languages AS l 
    ON u.id = l.id 
WHERE u.gender = "male" 
AND u.age BETWEEN 18 AND 24 // need claculation but let's keep it simple 
AND u.country = "US" 
AND ((l.language = "de_DE" AND l.mode = "learning" AND l.level = 1) OR (l.language = "ar_AR" AND l.mode = "learning" AND l.level = 4)) 
.... 
ORDER BY isOnline, lastLoginDate DESC 
LIMIT 0,10 

Мои вопросы:

  1. Как я могу построить запрос выше Firebase с фактической структурой
  2. Если это невозможно, как улучшить мою структуру базы данных для моего конкретного варианта использования (чтобы иметь возможность га ndle запрос выше лучшим образом)
+0

Рекомендуемое чтение: [Моделирование данных NoSQL] (https://highlyscalable.wordpress.com/2012/03/01/nosql-data-modeling-techniques/) и [мой ответ здесь] (http: // stackoverflow. com/questions/26700924/query-based-on-multiple-where-clauses-in-firebase) –

+0

Две вещи: пожалуйста, разместите свою структуру Firebase как текст, без изображений. Это облегчает копирование/вставку в ответ, а также делает его доступным для поиска. Консоль Firebase имеет функцию экспорта. Кроме того, сколько пользователей у вас будет онлайн в любой момент времени? – Jay

+0

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

ответ

8

Ответ на вопрос: вы не можете сделать этот тип - поиск в Firebase.

Позвольте мне представить ответ на стену, который, мы надеемся, приведет к решению.

Откровенно: Как уже упоминалось Франк в его на точке комментарии и ссылки, используя другие продукты, такие как ElasticSearch может быть одним из решений. Хотя они и обеспечивают масштабируемость, он добавляет еще один продукт в уравнение. Я бы предложил изучить эти варианты дальше.

Фильтр охлажден: Второе решение - фильтровать в коде. Хотя это хорошее решение для нескольких тысяч записей, оно не масштабируется для десятков/сотен тысяч записей. Однако это лучшее решение, если у вас сложная структура данных и ограниченное количество данных.

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

Изменение хорошее: Другой вариант - структурировать ваши данные в соответствии с типами запросов, которые вы будете выполнять. Для простого примера: предположим, что у вас есть три элемента, на которые вы хотите запросить; gender_country_age

Ваша Firebase структура будет

users 
    -Jyiai09jsi 
    data: "male_US_40" 
    -Jqkjisjida 
    date: "male_US_27" 
    -JyHYjlkall 
    data: "male_US_30" 

Тогда для запроса для всех пользователей мужского пола в США в возрасте от 30 до 40

usersRef.queryOrderedByChild("data").queryStartingAtValue("male_US_30") 
     .queryEndingAtValue("male_US_40").observeSingleEventOfType(
     .Value, withBlock: { snapshot in 
    print(snapshot) 
}) 

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

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

user_countries 
    US 
     -Jyiai09jsi: true 
     -Jqkjisjida: true 
     -JyHYjlkall: true 
    UK 
     etc etc 

user_gender 
    male 
     -Jyiai09jsi: true 
     -Jqkjisjida: true 
     -JyHYjlkall: true 
    female 
     etc etc 

user_speaks 
    da_UK 
     users 
    fr_FR 
     users 

Эта структура даст вам супер быстрый доступ к группам данных ; страны, пол и т. д. Я использовал здесь истину в качестве заполнителя, но технически вы могли бы иметь каждый узел пользователей в этом месте. Но это снова будет чтение во множестве данных во время запроса; куча «истинных» узлов - это довольно крошечный объем данных, даже с тысячами узлов.

SQL ftw! Что-то еще, чтобы рассмотреть, как вы используете асинхронный характер Firebase. Вам действительно нужно иметь эти данные, хранящиеся в Firebase, или вы можете хранить эти данные в другом облачном SQL-сервере для запросов и хранить ссылки на эти данные в Firebase. Таким образом, вы можете запросить SQL-запрос в своем сердце, а затем использовать Firebase для обмена сообщениями, обновлениями и т. Д.

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

Я надеюсь, что это поможет одна или их комбинация.

+1

Спасибо за еще один потрясающий ответ Jay! –

+0

@Jay, я застрял в одной проблеме относительно firebase. Я разместил вопрос о SO https://stackoverflow.com/questions/45433558/how-to-apply-multiple-filter-in-firebase-query-in-swift. – DJ1

Смежные вопросы