Firebase:如何查询来自两个节点的非重叠数据?

时间:2015-12-22 19:18:54

标签: angularjs firebase

这就是数据的样子:

datastructure

"uid0" : {
        "name": "adam"
},
"uid1" : {
        "name": "jonh",
        "likes" : {
          "uid2" : true
        }
},
"uid2" : {
        "name": "jane",
        "likes" : {
          "uid0" : true,
          "uid1" : true
        }
},
"uid3" : {
        "name": "mark"
}

如何找到uid2不喜欢的所有用户? (即结果应为uid3,在上述情况下)

codepen:http://codepen.io/rattanakchea/pen/gPwpQq?editors=101

firebase:https://datastructure.firebaseio.com/users.json

2 个答案:

答案 0 :(得分:2)

也许稍微不同的结构会提供更大的灵活性

     users
       -Ji94-0df-k00ksdf
         name: "john"
         liked: true
       -kKoakoksdookasdp
         name: "jane"
         liked: true
       -Lkaamsioadoisjg
         name: "james"
         liked: false

查询users = false

的用户节点

您可以通过添加say ..还是number_of_likes来扩展此功能

        users
               -Ji94-0df-k00ksdf
                 name: "john"
                 number_of_likes: 1,000,000
               -Lkaamsioadoisjg
                 name: "james"
                 number_of_likes: 0

您可以查询任何不喜欢(0)或最喜欢(1M)或其他任何内容的人

编辑:根据更新的信息更新并添加其他答案

有一些简单的解决方案:

一个是跟踪每个用户中的likes和no_status。使用这种结构很容易找到哪些用户uid_2不喜欢或不喜欢

user
  uid_0
    likes
     uid_1
     uid_2
    no_status
     uid_3
  uid_1
    likes
     uid_0
     uid_2
    no_status
     uid_3
  uid_2
    likes
     uid_0
     uid_1
    no_status
     uid_3

沿着同一行的另一个选择是转储布尔值并使用三态(或者需要很多状态)

user
  uid_0
    likable_status
     uid_1: "yes"
     uid_2: "no"
     uid_3: "unknown"
  uid_1
    likable_status
     uid_0: "yes"
     uid_2: "yes"
     uid_3: "unknown"
  uid_2
    likable_status
     uid_0: "yes"
     uid_1: "unknown"
     uid_3: "yes"

如果您想知道uid_2尚未决定哪些用户,请查询未知。

最后 - 您可以测试以查看节点是否存在。所以你可以读取一个节点,看看它是否存在:类似

ref = "/user/uid_2/liked/uid_3"

如果它不存在那么... uid_2不喜欢uid_3。

这里是一些obj c代码(来自firebase网站)

[ref observeEventType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot) {
  if (snapshot.value == [NSNull null]) {
    // The value is null
  }
}];

虽然这会测试单个节点,但构建一个uid列表并测试路径中的每个ref以查看它是否存在也是微不足道的。

注意: 磁盘空间便宜所以不要担心数据重复;它是NoSQL数据库中的标准做法,也是使它们快速尖叫的部分原因。

使用实际数据更新了修改

结构(请注意,在每个uid_x中;喜欢的是他们喜欢的人而不是他们不喜欢的人):

users
  uid_0
   liked
      uid_1: "yes"
   not_liked
      uid_2: "no"
      uid_3: "no"
 uid_1
   liked
      uid_0: "yes"
      uid_2: "yes"
   not_liked
      uid_3: "no"
 uid_2
   liked
      uid_0: "yes"
      uid_3: "yes"
   not_liked  
      uid_1: "no"
 uid_3
   liked
      uid_1: "yes"
   not_liked
      uid_0: "no"
      uid_2: "no"

代码:

Firebase *ref = [self.myRootRef childByAppendingPath:@"users"];

Firebase *userNotLikedRef = [ref childByAppendingPath:@"uid_2/not_liked"];

[userNotLikedRef observeEventType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot) {

   NSLog(@"%@", snapshot.value);

}];

这导致所有不喜欢的uid_2(在这种情况下为uid_1)

使用更平坦的结构和查询的另一个快速示例(注意每个uid_x节点中的子节点是谁喜欢它们的uid)

users
  uid_0
    uid_2: "yes"
    uid_3: "yes"
  uid_1
    uid_0: "yes"
    uid_2: "yes"
  uid_2
    uid_1: "yes"
    uid_3: "yes"
  uid_3
    uid_0: "yes"
    uid_1: "yes"

和查询

Firebase *ref = [self.myRootRef childByAppendingPath:@"users"];

FQuery *q1 = [ref queryOrderedByChild:@"uid_2"];
FQuery *q2 = [q1 queryEqualToValue:@"yes"];

[q2 observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {

    NSLog(@"%@", snapshot.value);

}];

这导致了uid_2喜欢的uid(uid_0和uid_1)

答案 1 :(得分:1)

Firebase的查询功能非常少,而且根据您当前的数据结构,无法在查询中获取所需信息。

您有三种选择:

  1. 取消整个用户集合并在javascript中找出它。根据集合的大小,这可能是可行的。只需创建一个userIds数组,并拼接出用户喜欢的列表中的任何内容。但是,从规模来看,这可能是太多数据无法立即下降。

  2. 为此目的创建和维护一个集合,一个notliked集合,每次新用户加入或用户喜欢另一个用户时都会更新。这看起来很笨拙。

  3. 在其他地方进行查询,在"真实"数据库。 Firebase非常适合很多事情,但如果您需要复杂的查询,则将其用作主数据存储区非常困难。我发现它作为来自另一个更强大的数据库的计算数据的前端最有用。它的优势在于其扩展和实时更新能力。