Swift中带有过滤器的高级Firebase查询 [英] Advanced Firebase Query with filter in Swift

查看:69
本文介绍了Swift中带有过滤器的高级Firebase查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚从关系数据库学校来,对新手来说,处理JSON数据库并非易事。我具有用于存储用户的结构:

I just came from the relational database school and dealing with JSON databases is not an easy task for new comers. I have this structure to store users:

{
  "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
      } ]
    }
  }
}

我在我的应用程序中提供了一个搜索屏幕,用户可以在其中搜索其他用户,他们可以结合所有以下过滤器参数:

I offer a search screen in my app where users can search for other users and they can combine all these filter parameters:

<强>示例:

获取 10 用户从索引0开始 c>谁:


  • 男性

  • 来自美国

  • 讲具有 levelID 2 或/和 fr_FR的 da_DK 任意级别的code>

  • and 学习 de_DE 级别1 **和/或** 学习 ar_AR 带有级别4

  • ,年龄在18至24之间的

  • 通过 isOnline 最后登录日期进行订购。

  • male
  • and from "US"
  • and speaks "da_DK" with levelID 2 or/and "fr_FR" with any level
  • and learns "de_DE"withlevel 1**and/or**learns "ar_AR"withlevel 4`
  • and with age range between 18 and 24
  • and order by isOnline and last login date.

在SQL中,假设有一个名为users_languages的表,这是一项简单的任务:

This is an easy task with SQL, when supposing that there is a table called 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. 如果无法针对特定用例改善数据库结构(以便能够以更好的方式处理上面的查询)


推荐答案

最关键的答案是:您不能这样做t ype是在Firebase中搜索。

The to-the-point answer is: You can't do this type is search in Firebase.

让我提出一个文字墙的答案,希望能找到解决方案。

Let me present a wall-of-text answer that will hopefully lead to a solution.

要坦率地说:
正如Frank在他的即时评论和链接中提到的那样,利用ElasticSearch等其他产品可以是一种解决方案。尽管它们确实提供了可伸缩性,但它为方程式增加了另一个乘积。我建议进一步探索这些选项。

To Be Quite Frank: As Frank had mentioned in his on-point comments and links, leveraging other products such as ElasticSearch can be one solution. While they do provide scalability, it adds another product to the equation. I would suggest exploring those options further.

过滤很酷:
第二种解决方案是过滤代码。虽然这对于成千上万的记录来说是一个很好的解决方案,但无法扩展成千上万的记录。但是,如果您具有复杂的数据结构和有限的数据量,这是最佳的解决方案。

Filtering is Cool: A second solution is to filter in code. While this is a good solution for a couple thousands records, it's not scalable for tens/hundreds of thousands of records. However, this is the best solution if you have a complex data structure and a limited amount of data.

请注意,即使有数百万条记录,也可以过滤代码如果用户界面的结构使其能够正常工作。确定一到两个主要搜索,例如性别。然后查询所有女性。这会将您的数据集减少一半,并且在代码中更易于管理。您还可以进一步减少数据集-请参阅下一节。

On that note, you can filter in code even with millions of records if the UI is structured to make it work. Decide on one to or two main searches, gender for example. Then perform a query for all females. That cuts your dataset by half and is much more manageable in code. You can also further reduce your dataset - see next section.

更改是好的:
另一个选择是将数据结构化为与您要执行的查询类型匹配。举一个简单的例子:假设您要查询三个项目; sex_country_age

Change is good: Another option is to structure your data to match the types of queries you will be performing. For a simple example: Suppose you have three items you want to query on; gender_country_age

您的Firebase结构将是

Your Firebase structure would be

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

然后查询美国30至40岁之间的所有男性用户

Then to query for all male users in the US between the ages of 30 and 40

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

这里的好处是它具有可扩展性,但缺点是您不能仅查询美国用户。另一方面,这是一个非常小的数据集,您可以在代码中进一步过滤。

The upside here is that's it's scalable but the downside is you can't query for just US users. On the flip side, this is a much smaller dataset which you could further filter in code.

重复的数据是您的朋友:
好消息是,还有一个解决方案:磁盘空间便宜,所以重复数据

Duplicate data is your friend: The good news is there's a solution for that as well: disk space is cheap so duplicate your data

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作为占位符,但从技术上讲,您也可以在该位置让每个用户节点。但是,这将再次在查询过程中读取大量数据。即使有成千上万个节点,一堆真实节点也只占很小的数据。

This structure give you super quick access to data groups; countries, gender etc. I used true here as a placeholder but technically you could have each users node in that spot as well. But, that would again be reading in a lot of data during the query; a bunch of 'true' nodes is a pretty tiny amount of data, even with thousands of nodes.

SQL ftw!
还有其他需要考虑的是您如何使用Firebase的异步特性。您是否真的需要将这些数据存储在Firebase中,还是可以将这些数据存储在另一个基于云的SQL Server中以进行查询并在Firebase中存储指向该数据的链接。这样,您可以通过SQL查询您的内心内容,然后使用Firebase进行消息传递,更新等。

SQL ftw! Something else to consider is how you are using the asynchronous nature of Firebase. Do you really need to have that data stored in Firebase or can you store that data in another cloud based SQL server for queries and store links to that data within Firebase. That way you can SQL query to your hearts content and then use Firebase for messaging, updates etc.

最终思想进行此类搜索的方法是,以尽可能快地减少数据足迹的方式来构造数据,然后用代码过滤其余数据。想象一下,拥有一百万条记录,然后查询male_US_30_FR。现在您有成千上万的记录,可以轻松地加载并通过代码进一步过滤

Final thought Your best bet if you want to to these kinds of searches is to structure your data in a way that reduces it's footprint as quickly as possible, then filter the rest in code. Imagine having a million records and then querying for male_US_30_FR. Now you have a couple of thousand records that's easily loaded and further filtered in code

我希望这些记录中的一个或两者有帮助。

I hope one or a combination of these helps.

这篇关于Swift中带有过滤器的高级Firebase查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆