47d*_*7d_ 227 firebase firebase-realtime-database
{
"movies": {
"movie1": {
"genre": "comedy",
"name": "As good as it gets",
"lead": "Jack Nicholson"
},
"movie2": {
"genre": "Horror",
"name": "The Shining",
"lead": "Jack Nicholson"
},
"movie3": {
"genre": "comedy",
"name": "The Mask",
"lead": "Jim Carrey"
}
}
}
Run Code Online (Sandbox Code Playgroud)
我是Firebase的新手.我如何可以检索从上面的数据结果,其中genre = 'comedy'与lead = 'Jack Nicholson'?
我有什么选择?
Fra*_*len 220
使用Firebase的查询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());
});
Run Code Online (Sandbox Code Playgroud)
但正如Firebase的@RobDiMarco在评论中所说:
多次
orderBy()调用将引发错误
所以我上面的代码不起作用.
我知道有三种方法可行.
你可以做的是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);
}
});
Run Code Online (Sandbox Code Playgroud)
如果这还不够好,您应该考虑修改/扩展您的数据以允许您的用例.例如:您可以将类型+引导填充到您刚刚用于此过滤器的单个属性中.
"movie1": {
"genre": "comedy",
"name": "As good as it gets",
"lead": "Jack Nicholson",
"genre_lead": "comedy_Jack Nicholson"
},...
Run Code Online (Sandbox Code Playgroud)
您实际上是以这种方式构建自己的多列索引,并可以使用以下方法查询它:
ref
.orderBy('genre_lead')
.equalTo('comedy_Jack Nicholson')
.on('child_added', function(snapshot) {
var movie = snapshot.val();
console.log(movie);
});
Run Code Online (Sandbox Code Playgroud)
David East编写了一个名为QueryBase的库,它可以帮助生成这些属性.
您甚至可以进行相对/范围查询,假设您希望允许按类别和年份查询电影.您将使用此数据结构:
"movie1": {
"genre": "comedy",
"name": "As good as it gets",
"lead": "Jack Nicholson",
"genre_year": "comedy_1997"
},...
Run Code Online (Sandbox Code Playgroud)
然后查询90年代的喜剧:
ref
.orderBy('genre_year')
.startAt('comedy_1990')
.endAt('comedy_2000')
.on('child_added', function(snapshot) {
var movie = snapshot.val();
console.log(movie);
});
Run Code Online (Sandbox Code Playgroud)
如果您需要过滤的不仅仅是年份,请确保按降序添加其他日期部分,例如"comedy_1997-12-25".这样,Firebase对字符串值执行的字典顺序将与按时间顺序排列相同.
属性中值的组合可以使用两个以上的值,但是您只能对复合属性中的最后一个值执行范围过滤.
一个非常特殊的变体是由Firebase的GeoFire库实现的.该库将位置的纬度和经度组合成所谓的Geohash,然后可以使用它在Firebase上进行实时范围查询.
另一种方法是在添加新的Query 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"
Run Code Online (Sandbox Code Playgroud)
可能有更多的方法.例如,此答案突出显示了另一种树形自定义索引:https://stackoverflow.com/a/34105063
Dav*_*ast 42
我写了一个个人库,允许您按多个值排序,所有订单都在服务器上完成.
Querybase接收Firebase数据库引用和您要索引的字段数组.当您创建新记录时,它将自动处理允许多次查询的密钥的生成.需要注意的是,它只支持直接等价(不小于或大于).
const databaseRef = firebase.database().ref().child('people');
const querybaseRef = querybase.ref(databaseRef, ['name', 'age', 'location']);
// Automatically handles composite keys
querybaseRef.push({
name: 'David',
age: 27,
location: 'SF'
});
// Find records by multiple fields
// returns a Firebase Database ref
const queriedDbRef = querybaseRef
.where({
name: 'David',
age: 27
});
// Listen for realtime updates
queriedDbRef.on('value', snap => console.log(snap));
Run Code Online (Sandbox Code Playgroud)
var ref = new Firebase('https://your.firebaseio.com/');
Query query = ref.orderByChild('genre').equalTo('comedy');
query.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot movieSnapshot : dataSnapshot.getChildren()) {
Movie movie = dataSnapshot.getValue(Movie.class);
if (movie.getLead().equals('Jack Nicholson')) {
console.log(movieSnapshot.getKey());
}
}
}
@Override
public void onCancelled(FirebaseError firebaseError) {
}
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
149873 次 |
| 最近记录: |