基于Firebase中多个where子句的查询 { “电影”:{ “电影1”:{ “类型”:“喜剧”, “名称”:“尽可能好”, “lead”:“Jack Nicholson” }, “电影2”:{ “类型”:“恐怖”, “名称”:“闪光”, “lead”:“Jack Nicholson” }, “电影3”:{ “类型”:“喜剧”, “姓名”:“面具”, “领导”:“吉姆·凯利” } } }

基于Firebase中多个where子句的查询 { “电影”:{ “电影1”:{ “类型”:“喜剧”, “名称”:“尽可能好”, “lead”:“Jack Nicholson” }, “电影2”:{ “类型”:“恐怖”, “名称”:“闪光”, “lead”:“Jack Nicholson” }, “电影3”:{ “类型”:“喜剧”, “姓名”:“面具”, “领导”:“吉姆·凯利” } } },firebase,firebase-realtime-database,Firebase,Firebase Realtime Database,我是一个火箭筒新手。如何从上面的数据中检索结果,其中类型='喜剧'和线索='杰克·尼科尔森' 我有什么选择?使用,您可能会尝试以下方法: /!!!这行不通!!! 裁判 .orderBy('流派') .startAt(“喜剧”).endAt(“喜剧”) .orderBy('lead')/!!!此行将引发错误!!! .startAt(“杰克·尼科尔森”).endAt(“杰克·尼科尔森”) .on('value',函数(快照){ console.log(snapshot.val()); }); 但正

我是一个火箭筒新手。如何从上面的数据中检索结果,其中
类型='喜剧'
线索='杰克·尼科尔森'

我有什么选择?

使用,您可能会尝试以下方法:

/!!!这行不通!!!
裁判
.orderBy('流派')
.startAt(“喜剧”).endAt(“喜剧”)
.orderBy('lead')/!!!此行将引发错误!!!
.startAt(“杰克·尼科尔森”).endAt(“杰克·尼科尔森”)
.on('value',函数(快照){
console.log(snapshot.val());
});
但正如Firebase的@RobDiMarco在评论中所说:

多个
orderBy()
调用将引发错误

因此,我上面的代码将不起作用

我知道有三种方法可以奏效

1.在服务器上筛选大部分,在客户端执行其余操作 您可以做的是在服务器上执行一个
orderBy().startAt()./endAt()
,下拉剩余数据并在客户端的JavaScript代码中对其进行过滤

ref
.orderBy('流派')
.equalTo(“喜剧”)
.on('child_added',函数(快照){
var movie=snapshot.val();
如果(movie.lead=='Jack Nicholson'){
console.log(电影);
}
});
2.添加一个属性,该属性组合要筛选的值

如果这不够好,你应该考虑修改/扩展你的数据以允许你的用例。例如:您可以将“流派+导语”填充到一个仅用于此筛选器的属性中

“电影1”:{
“类型”:“喜剧”,
“名称”:“尽可能好”,
“领导”:“杰克·尼科尔森”,
“流派领袖”:“喜剧杰克·尼科尔森”
}, //...
实际上,您正在以这种方式构建自己的多列索引,并可以使用以下工具进行查询:

ref
.orderBy('GREEN_lead')
.equalTo(“喜剧”杰克·尼科尔森)
.on('child_added',函数(快照){
var movie=snapshot.val();
console.log(电影);
});
大卫·伊斯特写了一篇文章

您甚至可以进行相对/范围查询,假设您希望允许按类别和年份查询电影。您将使用以下数据结构:

“电影1”:{
“类型”:“喜剧”,
“名称”:“尽可能好”,
“领导”:“杰克·尼科尔森”,
“类型年”:“喜剧年1997”
}, //...
然后查询90年代的喜剧:

ref
.orderBy('类型\年份')
.startAt(‘喜剧’1990’)
.endAt('Cometic_2000')
.on('child_added',函数(快照){
var movie=snapshot.val();
console.log(电影);
});
如果您需要过滤的不仅仅是年份,请确保按降序添加其他日期部分,例如,
“喜剧1997-12-25”
。这样Firebase对字符串值进行的词典排序将与时间排序相同

属性中的值的这种组合可以使用两个以上的值,但只能对复合属性中的最后一个值进行范围筛选

一个非常特殊的变体由实现。该库将一个位置的纬度和经度组合成一个所谓的函数,然后可以使用该函数在Firebase上进行实时范围查询

3.以编程方式创建自定义索引 另一种选择是执行添加此新查询API之前我们都做过的操作:在其他节点中创建索引:

“电影”
//与今天的结构相同
“按流派”
“喜剧”
“由你牵头”
“杰克·尼科尔森”
“电影1”
“吉姆·凯瑞”
“电影3”
“恐怖”
“由你牵头”
“杰克·尼科尔森”
“电影2”
可能还有更多的方法。例如,此答案突出显示了另一种树形自定义索引:


如果这些选项中没有一个为您工作,但您仍然希望将数据存储在Firebase中,您也可以考虑使用ITS.< /P>


CloudFireStore可以在一个查询中处理多个相等筛选器,但只能处理一个范围筛选器。实际上,它使用的是相同的查询模型,但就像它自动为您生成复合属性一样。请参阅上的Firestore文档。

我编写了一个个人库,允许您按多个值进行订购,所有订购都在服务器上完成

Querybase接收Firebase数据库引用和您希望索引的字段数组。当您创建新记录时,它将自动处理允许多次查询的密钥的生成。需要注意的是,它只支持直线等价(不小于或大于)


这将起作用。

弗兰克的回答很好,但最近推出的Firestore使操作和查询更容易

您可以创建一个
过滤器
字段来添加过滤器。您可以根据需要添加任意多的值。例如,要按喜剧和杰克·尼科尔森进行筛选,您可以添加值
喜剧\u杰克·尼科尔森
,但如果您也想按喜剧和2014进行筛选,则可以添加值
喜剧\u 2014
,而无需创建更多字段

{
“电影”:{
“电影1”:{
“类型”:“喜剧”,
“名称”:“尽可能好”,
“领导”:“杰克·尼科尔森”,
“年份”:2014年,
“过滤器”:[
“喜剧杰克·尼科尔森”,
“喜剧之夜2014”
]
}
}
}

Firebase不允许使用多个条件进行查询。 然而,我确实找到了解决这个问题的方法:

我们需要从数据库下载初始过滤数据并存储
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) {

    }
});
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));
ref.orderByChild("lead").startAt("Jack Nicholson").endAt("Jack Nicholson").listner....
                Query query = databaseReference.orderByChild("genre").equalTo("comedy");
                databaseReference.addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                        ArrayList<Movie> movies = new ArrayList<>();
                        for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
                            String lead = dataSnapshot1.child("lead").getValue(String.class);
                            String genre = dataSnapshot1.child("genre").getValue(String.class);

                            movie = new Movie(lead, genre);

                            movies.add(movie);

                        }

                        filterResults(movies, "Jack Nicholson");

                        }

                    }

                    @Override
                    public void onCancelled(@NonNull DatabaseError databaseError) {

                    }
                });
public void filterResults(final List<Movie> list,  final String genre) {
        List<Movie> movies = new ArrayList<>();
        movies = list.stream().filter(o -> o.getLead().equals(genre)).collect(Collectors.toList());
        System.out.println(movies);

        employees.forEach(movie -> System.out.println(movie.getFirstName()));
    }
static getOnilineUsersUID() {
var dbRef = FirebaseDatabase.instance;
DatabaseReference reference = dbRef.reference().child("Online");
reference.once().then((value) {
  Map<String, bool> map = Map<String, bool>.from(value.value);
  List users = [];
  map.forEach((key, value) {
    if (value) {
      users.add(key);
    }
  });
  print(users);
});