firebase - Firebase中基于多个where子句的查询

标签 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"
    }
  }
}

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

我有什么选择?

最佳答案

使用Firebase's 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 在评论中所说:

multiple orderBy() calls will throw an error

所以我上面的代码将无法工作

我知道三种可行的方法。

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。添加一个属性来组合您要过滤的值

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

"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 写了 library called QueryBase that helps with generating such properties .

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

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

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

一个非常特殊的变体是由 GeoFire library for Firebase 实现的。 。该库将位置的纬度和经度组合成所谓的 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

<小时/>

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

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

关于firebase - Firebase中基于多个where子句的查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51116159/

相关文章:

firebase - 仅使用 'once()' 回调的 Firebase 客户端是否算作并发用户?

Swift 闭包不设置变量

firebase - Flutter Firestore : An error occurred while parsing query arguments on using whereNotIn and arrayContains at the same query

firebase - 如何使用 Firebase 身份验证获取 google api 的刷新 token

javascript - Firebase 查询子级的子级是否包含值

ios - 应用程序将数据重置为零,即使它存储在 firebase 上

firebase - 如何在使用 Golang 推送 Firebase 后提取自动生成的唯一 ID?

javascript - Firebase 推送 1 个输入值而不是 Span?

当我编写 FirebaseApp.configure() 时,iOS 应用程序崩溃

node.js - 在 node.js 中使用 Firebase Admin SDK 发送消息时尝试使用 FCM 服务器进行身份验证时出错