我已经从parse-server转移到firebase用于我的新项目,但是在项目中我已经开始认为这是一个坏主意。
基本上,我正在创建一个应用程序,人们可以在其中发布有关他们镇上的音乐会的信息。
我的第一个挑战是过滤事件,因此用户只能在他/她自己的城镇中获取事件。我通过构建城市之后的数据来做到这一点:
{
concerts: {
"New york": {
...,
...
},
"Chicago": {
...,
...
}
}
}
然后我想我需要另一种音乐会类型的过滤器,例如摇滚,流行音乐等。所以我虽然做了另一次重组。但是,可能需要再增加5到10个过滤器,并且很难以良好的方式构建数据库。
我关于多个查询,但不允许这样做:
firebase.database().ref("concerts")
.orderByChild("type").equalTo("rock")
.orderByChild("length").equalTo("2")
.orderByChild("artist").equalTo("beatles")
我考虑过从服务器获取所有内容,然后在客户端中过滤结果。不过我看到了两个问题:
我考虑过将过滤器组合起来创建查询键,例如this,但是使用10多个过滤器,它会变得复杂。
是否有解决方案或者我应该忘记这个用例的firebase?
提前致谢
答案 0 :(得分:4)
可以在Firebase中制作难以置信的复杂查询。数据需要存储在一个有待查询的结构中,最重要的是,不要害怕重复数据。
例如,假设我们有一个应用程序,使用户可以选择特定年份和月份,特定城市和特定类型的音乐会。
有3个参数
YEAR_MONTH 市 流派
UI首先查询用户以选择城市
Austin
然后用户界面要求选择年份和月份
201704
然后是一种类型
Rock
您的Firebase结构如下所示
concerts
concert_00
city: Memphis
year_month: 201706
genre: Country
city_date_genre: Memphis_201606_Country
concert_01
city: Austin
year_month: 201704
genre: Rock
city_date_genre: Austin_201704_Rock
concert_02
city: Seattle
year_month: 201705
genre: Disco
city_date_genre: Seattle_201705_Disco
您的用户界面已经在用户中查询了查询信息,并使用该信息构建查询字符串
Austin_201704_Rock
然后查询' city_date_genre'该字符串的节点,您有数据。
如果用户想要了解2017年4月奥斯汀的所有音乐会,该怎么办
queryStartingAt("Austin_201704").queryEndingAt("Austin_201704")
您可以通过添加另一个查询节点并更改数据的顺序
来轻松扩展此功能concerts
concert_00
city: Memphis
year_month: 201706
genre: Country
city_date_genre: Memphis_201606_Country
city_genre_date: Memphis_Country_201606
根据用户选择数据的顺序,您可以查询关联的节点。
添加额外的节点是一个很小的数据,并允许对您需要的数据进行非常开放的查询。
答案 1 :(得分:0)
我看到这是一篇旧帖子,但我想借此机会将遇到类似 Firebase 问题的其他人指向 AceBase,它是 Firebase 实时数据库的免费开源替代品. Firebase 中缺乏适当的查询和索引选项是构建 AceBase 的原因之一。使用 AceBase 可以让您像这样查询数据:
const snapshots = await db.ref('concerts')
.query()
.filter('city', '==', 'New York')
.filter('date', 'between', [today, nextWeek]) // today & nextWeek being Dates
.filter('genre', 'in', ['rock', 'blues', 'country'])
.get();
因为 AceBase 支持索引,向查询字段添加 1 个或多个索引将使这些查询运行得非常快,即使有数百万条记录。它支持简单索引,但也支持全文和地理索引,因此您还可以使用位置和关键字查询您的数据:
.filter('location', 'geo:nearby', { lat: 40.730610, long: -73.935242, radius: 10000 }) // New York center with 10km radius
.filter('title', 'fulltext:contains', '"John Mayer" OR "Kenny Wayne Shepherd"')
如果您想限制结果以允许分页,只需添加跳过和限制:.skip(80).limit(20)
此外,如果您想让查询提供实时结果,以便任何新添加的音乐会立即通知您的应用 - 只需添加事件侦听器即可将其升级为实时查询:
const results = await db.ref('concerts')
.filter('location', 'geo:nearby', { lat: 40.730610, long: -73.935242, radius: 10000 })
.on('add', addConcert)
.on('remove', removeConcert)
.get();
function addConcert(match) {
results.push(match.snapshot);
updateUI();
}
function removeConcert(match) {
const index = results.findIndex(r => r.ref.path === match.ref.path);
results.splice(index, 1);
updateUI();
}
如果您想了解有关 AceBase 的更多信息,请访问 npm:https://www.npmjs.com/package/acebase。 AceBase 是免费的,其全部源代码可在 GitHub 上获得。玩得开心!