【问题标题】:Firebase - Deep Query orderByChild with equalToFirebase - 使用 equalTo 进行深度查询 orderByChild
【发布时间】:2016-02-17 02:14:12
【问题描述】:

我试图通过其中的成员来获取每个项目——我已经创建了一个示例数据结构,尽管实际结构要大得多(因为它很难重组数据库)。

这是我的查询:

var ref = new Firebase(FBURL + '/chat/meta/project');

var email = 'kerry@email.com';

ref
    .orderByChild("email")
    .equalTo(email)
    .on("child_added", function(snapshot) {
        console.log(snapshot.val());
    }
);

重要的是要注意,如果我删除它返回所有“项目”的.equalTo(email),它应该只返回其中的 2 个。

这是 Firebase 中的数据:

{
  "chat" : {
    "meta" : {
      "project" : {
        "-KAgjWOxjk80HIbNr68M" : {
          "name" : "Gman Branding",
          "url" : "http://localhost:3000/project/abc123fasd123cc/...",
          "date" : "2015-10-10T21:33:25.170Z",
          "member" : {
            "-KAgkD-2GVESwNwKP3fA" : {
              "email" : "abc@gman.com"
            },
            "-KAgkP3M4nug9Bjn-vY6" : {
              "email" : "def@gman.com"
            },
            "-KAgkP3OF0sUgc9x9p37" : {
              "email" : "ghi@gman.com"
            },
            "-KAgkaMyEOiXft6o-HbO" : {
              "email" : "kerry@email.com"
            }
          }
        },
        "-KAgl9xlPDU5T4072FgE" : {
          "-KAglqH9pxkhgC84_kAl" : {
            "name" : "YuDog",
            "url" : "http://localhost:3000/project/abc123fasd123cc/...",
            "date" : "2015-10-10T21:41:31.172Z"
          },
          "name" : "billing test 1",
          "url" : "http://localhost:3000/project/abc123fasd123cc/...",
          "date" : "2015-02-25T23:18:55.626Z",
          "dateNotifyUnread" : "2016-01-25T23:23:55.626Z",
          "member" : {
            "-KAglNsswyk66qUZNrTU" : {
              "email" : "kerry@email.com"
            }
          }
        },
        "-KAgltmLk2oOYhEDfwRL" : {
          "-KAgm1Jt5q53gzLm1GIh" : {
            "name" : "YuDog",
            "url" : "http://localhost:3000/project/abc123fasd123cc/...",
            "date" : "2015-10-10T21:41:31.172Z"
          },
          "name" : "YuDog",
          "url" : "http://localhost:3000/project/abc123fasd123cc/...",
          "date" : "2015-10-10T21:41:31.172Z",
          "member" : {
            "-KAgm1Jvss9AMZa1qDb7" : {
              "email" : "joe@yudog.com"
            }
          }
        },
        "-KAgluTcE_2dv00XDm1L" : {
          "-KAgm6ENmkpDiDG2lqZ4" : {
            "name" : "YuDog Landing Page",
            "url" : "http://localhost:3000/project/abc123fasd123cc/...",
            "date" : "2015-10-10T21:41:31.172Z"
          },
          "-KAgmBptbeInutRzNinm" : {
            "name" : "YuDog Landing Page",
            "url" : "http://localhost:3000/project/abc123fasd123cc/...",
            "date" : "2015-10-10T21:41:31.172Z"
          },
          "name" : "YuDog Landing Page",
          "url" : "http://localhost:3000/project/abc123fasd123cc/...",
          "date" : "2015-10-10T21:41:31.172Z",
          "member" : {
            "-KAgm6EQcvQg3oP-OnIF" : {
              "email" : "joe@yudog.com"
            },
            "-KAgmBpwoxPYGXS9fLZ9" : {
              "email" : "joe@yudog.com"
            }
          }
        }
      }
    }
  }
}

我查看了 SO 上的 8-10 个其他链接,但没有找到任何可以解决此问题的链接。

【问题讨论】:

    标签: javascript firebase firebase-realtime-database


    【解决方案1】:

    解决方案是创建符合您需求的数据结构。在这种情况下,您希望根据用户的电子邮件地址查找用户的项目。所以我们将添加一个包含这个映射的节点:

    "projects_by_email": {
      "kerry@email,com": {
        "-KAgjWOxjk80HIbNr68M": true,
        "-KAgl9xlPDU5T4072FgE": true
      },
      "abc@gman,com": {
        "-KAgjWOxjk80HIbNr68M": true
      }
      ...
    }
    

    这称为非规范化数据,尽管我经常将它们视为倒排索引。我可能会按 uid 保留项目,但结构是一样的。

    使用这样的结构,您可以通过简单的直接查找来获取电子邮件的项目列表:

    var ref = new Firebase(FBURL);
    var email = 'kerry@email.com';
    ref.child('projects_by_email')
       .child(email)
       .on("child_added", function(snapshot) {
           console.log(snapshot.key());
       }
    );
    

    或者,如果您还想自己“加入”项目:

    var ref = new Firebase(FBURL);
    var email = 'kerry@email.com';
    ref.child('projects_by_email')
       .child(email)
       .on("child_added", function(snapshot) {
           ref.child('project').child(snapshot.key()).once('value', function(projectSnapshot) {
               console.log(projectSnapshot.val());
           });
       }
    );
    

    这种类型的非规范化是 NoSQL 数据建模的正常部分。重复可能会让人觉得很浪费,但这也是 NoSQL 解决方案规模如此之大的部分原因:上面的代码都没有要求数据库考虑所有项目/所有用户。这一切都是直接访问正确的节点,可以很好地扩展。所以我们牺牲了存储空间来提高性能/可扩展性;典型的空间与时间权衡。

    【讨论】:

    • 嗨弗兰克,感谢您的回复,但我正在寻找一种无需修改任何结构的方法
    • 唯一的方法是在每个推送 ID 上添加一个深度索引。 "-KAgkD-2GVESwNwKP3fA""-KAgkP3M4nug9Bjn-vY6" 等。我怀疑这也是你想要的。在 NoSQL 中,您经常按照您想要的访问方式对数据进行建模。有关此内容以及更多内容,请参阅NoSQL data modeling 上的这篇文章。
    • 看起来电子邮件格式不允许作为键,我明白了:第一个参数是无效路径:“e.mail@mail.com”。路径必须是非空字符串,并且不能包含“.”、“#”、“$”、“[”或“]”
    • 是的,我应该更明确一点:当使用电子邮件地址作为密钥时,您应该对其进行编码。通常,开发人员将. 更改为,,这在电子邮件地址中是不允许的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-22
    • 2021-12-24
    • 1970-01-01
    • 2018-03-28
    • 1970-01-01
    • 2018-08-14
    • 1970-01-01
    相关资源
    最近更新 更多