基于 Firebase 中多个 where 子句的查询 [英] Query based on multiple where clauses in Firebase

查看:30
本文介绍了基于 Firebase 中多个 where 子句的查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我是 Firebase 新手.如何从上述数据中检索结果where genre = 'comedy' AND lead = 'Jack Nicholson'?

I am a Firebase newbie. How can I retrieve a result from the data above where genre = 'comedy' AND lead = 'Jack Nicholson'?

我有哪些选择?

推荐答案

使用 Firebase 的查询 API,你可能会想试试这个:

Using Firebase's Query API, you might be tempted to try this:

// !!! 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 在评论中所说:

But as @RobDiMarco from Firebase says in the comments:

多次orderBy()调用会抛出错误

所以我上面的代码不起作用.

我知道三种可行的方法.

I know of three approaches that will work.

可以做的是在服务器上执行一个orderBy().startAt()./endAt(),下拉剩余的数据并在JavaScript中过滤它客户端上的代码.

What you can do is execute one orderBy().startAt()./endAt() on the server, pull down the remaining data and filter that in JavaScript code on your client.

ref
  .orderBy('genre')
  .equalTo('comedy')
  .on('child_added', function(snapshot) { 
      var movie = snapshot.val();
      if (movie.lead == 'Jack Nicholson') {
          console.log(movie);
      }
  });

2.添加一个属性来组合您要过滤的值

如果这还不够好,您应该考虑修改/扩展您的数据以允许您的用例.例如:您可以将流派+线索填充到您仅用于此过滤器的单个属性中.

2. add a property that combines the values that you want to filter on

If that isn't good enough, you should consider modifying/expanding your data to allow your use-case. For example: you could stuff genre+lead into a single property that you just use for this filter.

"movie1": {
    "genre": "comedy",
    "name": "As good as it gets",
    "lead": "Jack Nicholson",
    "genre_lead": "comedy_Jack Nicholson"
}, //...

您实际上是在以这种方式构建自己的多列索引,并且可以使用以下方式进行查询:

You're essentially building your own multi-column index that way and can query it with:

ref
  .orderBy('genre_lead')
  .equalTo('comedy_Jack Nicholson')
  .on('child_added', function(snapshot) { 
      var movie = snapshot.val();
      console.log(movie);
  });

David East 编写了一个名为 QueryBase 的库,可帮助生成此类属性.

David East has written a library called QueryBase that helps with generating such properties.

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

You could even do relative/range queries, let's say that you want to allow querying movies by category and year. You'd use this data structure:

"movie1": {
    "genre": "comedy",
    "name": "As good as it gets",
    "lead": "Jack Nicholson",
    "genre_year": "comedy_1997"
}, //...

然后查询 90 年代的喜剧:

And then query for comedies of the 90s with:

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 对字符串值的字典顺序将与时间顺序相同.

If you need to filter on more than just the year, make sure to add the other date parts in descending order, e.g. "comedy_1997-12-25". This way the lexicographical ordering that Firebase does on string values will be the same as the chronological ordering.

属性中值的这种组合可以处理两个以上的值,但您只能对复合属性中的最后一个值进行范围过滤.

This combining of values in a property can work with more than two values, but you can only do a range filter on the last value in the composite property.

用于 Firebase 的 GeoFire 库 实现了一个非常特殊的变体.这个库将一个位置的纬度和经度组合成一个所谓的 Geohash,然后可以用于在 Firebase 上进行实时范围查询.

A very special variant of this is implemented by the GeoFire library for Firebase. This library combines the latitude and longitude of a location into a so-called Geohash, which can then be used to do realtime range queries on Firebase.

另一种替代方法是在添加这个新的查询 API 之前完成我们所做的一切:在不同的节点中创建索引:

Yet another alternative is to do what we've all done before this new Query API was added: create an index in a different node:

  "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

There are probably more approaches. For example, this answer highlights an alternative tree-shaped custom index: https://stackoverflow.com/a/34105063

如果这些选项都不适合您,但您仍想将数据存储在 Firebase 中,您还可以考虑使用其 Cloud Firestore 数据库.

If none of these options work for you, but you still want to store your data in Firebase, you can also consider using its Cloud Firestore database.

Cloud Firestore 可以在单个查询中处理多个相等过滤器,但只能处理一个范围过滤器.在幕后,它本质上使用相同的查询模型,但它就像为您自动生成复合属性.请参阅 Firestore 关于复合查询的文档.

Cloud Firestore can handle multiple equality filters in a single query, but only one range filter. Under the hood it essentially uses the same query model, but it's like it auto-generates the composite properties for you. See Firestore's documentation on compound queries.

这篇关于基于 Firebase 中多个 where 子句的查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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