iOS*_*eek 5 database-design ios firebase swift firebase-realtime-database
我刚刚来自关系数据库学校,处理JSON数据库对新来者来说并不是一件容易的事.我有这个结构来存储用户:
{
"users" : {
"0CcKvNkOm5fVqL" : {
"birthday" : 564688000,
"country" : "US",
"email" : "email@live.com",
"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
} ]
}
}
}
Run Code Online (Sandbox Code Playgroud)
我在我的应用程序中提供了一个搜索屏幕,用户可以搜索其他用户,他们可以组合所有这些过滤器参数:
例:
获取以下10
用户starting from index 0
:
male
"US"
speaks "da_DK"
用levelID 2
或/和 "fr_FR"
用any level
with
等级1 **and/or**
学习"ar_AR" with
等级4`age range between 18 and 24
isOnline
和 last login date
.当假设有一个名为users_languages的表时,这是一个简单的SQL任务:
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
Run Code Online (Sandbox Code Playgroud)
我的问题:
最重要的答案是:你不能在Firebase中搜索这种类型.
让我提出一个墙上的答案,希望能够找到解决方案.
坦率地说: 正如弗兰克在他的论点和链接中提到的那样,利用ElasticSearch等其他产品可以成为一种解决方案.虽然它们确实提供了可扩展性,但它增加了另一种产品.我建议进一步探讨这些选择.
过滤很酷: 第二种解决方案是过滤代码.虽然这对于成千上万条记录来说是一个很好的解决方案,但它不能扩展到数十/数十万条记录.但是,如果您具有复杂的数据结构和有限的数据量,这是最佳解决方案.
在这方面,如果UI的结构使其工作,您甚至可以使用数百万条记录来过滤代码.确定一到两个主要搜索,例如性别.然后对所有女性执行查询.这会将您的数据集减少一半,并且在代码中更易于管理.您还可以进一步减少数据集 - 请参阅下一节.
变化是好的: 另一种选择是构建数据以匹配您将要执行的查询类型.举个简单的例子:假设您有三个要查询的项目; gender_country_age
您的Firebase结构将是
users
-Jyiai09jsi
data: "male_US_40"
-Jqkjisjida
date: "male_US_27"
-JyHYjlkall
data: "male_US_30"
Run Code Online (Sandbox Code Playgroud)
然后查询年龄在30到40岁之间的美国所有男性用户
usersRef.queryOrderedByChild("data").queryStartingAtValue("male_US_30")
.queryEndingAtValue("male_US_40").observeSingleEventOfType(
.Value, withBlock: { snapshot in
print(snapshot)
})
Run Code Online (Sandbox Code Playgroud)
这里的优势在于它的可扩展性,但缺点是你不能只查询美国用户.另一方面,这是一个小得多的数据集,您可以在代码中进一步过滤.
重复数据是你的朋友: 好消息是有一个解决方案:磁盘空间很便宜,所以复制你的数据
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
Run Code Online (Sandbox Code Playgroud)
这种结构使您可以超级快速地访问数据组; 国家,性别等我在这里使用true作为占位符,但从技术上讲,你也可以在该位置拥有每个用户节点.但是,在查询期间,这将再次读取大量数据; 即使有数千个节点,一堆"真正的"节点也是一个非常少量的数据.
SQL ftw! 还需要考虑的是如何使用Firebase的异步特性.您是否真的需要将这些数据存储在Firebase中,或者您是否可以将该数据存储在另一个基于云的SQL服务器中,以便在Firebase中查询和存储指向该数据的链接.这样您就可以通过SQL查询您的内容,然后使用Firebase进行消息传递,更新等.
最后的想法如果你想要进行这些类型的搜索,最好的选择是以尽可能快地减少其占用空间的方式构建数据,然后在代码中过滤其余部分.想象一下,有一百万条记录,然后查询male_US_30_FR.现在,您有几千条记录可以轻松加载并在代码中进一步过滤
我希望这些中的一个或组合有所帮助.
归档时间: |
|
查看次数: |
2016 次 |
最近记录: |