在Swift中使用filter的高级Firebase查询
我刚刚来自关系数据库学校,处理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 } ] } } }
我在我的应用程序中提供了一个搜索屏幕,用户可以搜索其他用户,他们可以组合所有这些filter参数:
例:
starting from index 0
获得10
用户:
-
male
- 来自
"US"
- 并且使用
levelID 2
或/和"fr_FR"
以any level
speaks "da_DK"
- 并且学习“de_DE”级别1
**and/or**
学习“ar_AR”级别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
我的问题:
- 如何使用Firebase和实际结构构建上面的查询
- 如果不可能如何改进我的特定用例的数据库结构(以更好的方式处理上面的查询)
最重要的答案是:你不能在Firebase中搜索这种类型。
让我提出一个墙上的答案,希望能够找到解决方案。
坦白说:正如弗兰克在他的论点和链接中所提到的,利用ElasticSearch等其他产品可以成为一种解决方案。 虽然它们确实提供了可扩展性,但它增加了另一种产品。 我建议进一步探讨这些选择。
过滤很酷:第二种解决方案是过滤代码。 虽然这对于成千上万条记录来说是一个很好的解决方案,但它不能扩展到数十/数十万条记录。 但是,如果您具有复杂的数据结构和有限的数据量,这是最佳解决方案。
在这方面,如果UI的结构使其工作,您甚至可以使用数百万条记录来过滤代码。 确定一到两个主要搜索,例如性别。 然后对所有女性执行查询。 这会将您的数据集减少一半,并且在代码中更易于管理。 您还可以进一步减少数据集 – 请参阅下一节。
变化很好:另一个选择是构建数据以匹配您将要执行的查询类型。 举个简单的例子:假设您有三个要查询的项目; 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
这种结构使您可以超级快速地访问数据组; 国家,性别等我在这里使用true作为占位符,但从技术上讲,您也可以在该位置拥有每个用户节点。 但是,在查询期间,这将再次读取大量数据; 即使有数千个节点,一堆“真正的”节点也是非常少量的数据。
SQL ftw! 还需要考虑的是如何使用Firebase的异步特性。 您是否真的需要将这些数据存储在Firebase中,或者您是否可以将该数据存储在另一个基于云的SQL服务器中,以便在Firebase中查询和存储指向该数据的链接。 这样你就可以对你的内容进行SQL查询,然后使用Firebase进行消息传递,更新等。
最后的想法如果你想要进行这些类型的搜索,最好的办法就是以尽可能快地减少数据占用空间的方式构建数据,然后在代码中过滤剩下的数据。 想象一下,有一百万条记录,然后查询male_US_30_FR。 现在,您有几千条记录可以轻松加载并在代码中进一步过滤
我希望这些中的一个或组合有所帮助。