使用Firebase的Query API,您可能会想尝试以下方法:
// !!! THIS WILL NOT WORK !!!
ref
.orderBy('genre')
.startAt('comedy').endAt('comedy')
.orderBy('lead') // !!! THIS LINE WILL RAISE AN ERROR !!!
.startAt('Jack Nicholson').endAt('Jack Nicholson')
.on('value', function(snapshot) {
console.log(snapshot.val());
});
但是正如Firebase的@RobDiMarco在评论中所说:
多次orderBy()
通话将引发错误
所以我上面的代码将无法工作。
我知道三种可行的方法。
1.在服务器上过滤最多的内容,其余在客户端上进行
您可以做的是orderBy().startAt()./endAt()
在服务器上执行一个,下拉剩余的数据,然后在客户端的JavaScript代码中进行过滤。
ref
.orderBy('genre')
.equalTo('comedy')
.on('child_added', function(snapshot) {
var movie = snapshot.val();
if (movie.lead == 'Jack Nicholson') {
console.log(movie);
}
});
2.添加一个属性,该属性组合了要过滤的值
如果这还不够好,则应考虑修改/扩展数据以允许用例。例如:您可以将genre + lead填充到一个仅用于此过滤器的属性中。
"movie1": {
"genre": "comedy",
"name": "As good as it gets",
"lead": "Jack Nicholson",
"genre_lead": "comedy_Jack Nicholson"
},...
本质上,您是以这种方式构建自己的多列索引,并且可以使用以下查询它:
ref
.orderBy('genre_lead')
.equalTo('comedy_Jack Nicholson')
.on('child_added', function(snapshot) {
var movie = snapshot.val();
console.log(movie);
});
David East编写了一个名为QueryBase的库,该库有助于生成此类属性。
您甚至可以进行相对/范围查询,假设您要允许按类别和年份查询电影。您将使用以下数据结构:
"movie1": {
"genre": "comedy",
"name": "As good as it gets",
"lead": "Jack Nicholson",
"genre_year": "comedy_1997"
},...
然后使用以下内容查询90年代的喜剧:
ref
.orderBy('genre_year')
.startAt('comedy_1990')
.endAt('comedy_2000')
.on('child_added', function(snapshot) {
var movie = snapshot.val();
console.log(movie);
});
如果您需要过滤的不只是年份,请确保按降序添加其他日期部分,例如"comedy_1997-12-25"
。这样,Firebase对字符串值进行的词典编排顺序将与时间顺序相同。
属性中值的这种组合可以使用两个以上的值,但是您只能对Composite属性中的最后一个值进行范围过滤。
这是一个非常特殊的变体,由Firebase的GeoFire库实现。该库将位置的纬度和经度组合到所谓的Geohash中,然后可用于在Firebase上进行实时范围查询。
3.以编程方式创建自定义索引
还有另一种方法是在添加新的查询API之前做所有事情:在另一个节点中创建索引:
"movies"
// the same structure you have today
"by_genre"
"comedy"
"by_lead"
"Jack Nicholson"
"movie1"
"Jim Carrey"
"movie3"
"Horror"
"by_lead"
"Jack Nicholson"
"movie2"
可能有更多的方法。例如,此答案突出显示了另一种树形自定义索引:https : //stackoverflow.com/a/34105063
orderBy()
调用将引发错误,因为客户端当前给出了意外的结果。它有可能在您的测试中偶然起作用,但并不是为了一般情况而设计(尽管我们很乐意添加它!)。