【问题标题】:How to query firebase for property with specific value inside all children如何在所有子项中查询具有特定值的属性的firebase
【发布时间】:2014-10-06 00:44:55
【问题描述】:

我有这个数据结构,todos 按照路径 /todos/uid/ 进行组织

{
  "metausers" : {
    "simplelogin:1" : {
      "displayName" : "John Doe",
      "provider" : "password",
      "provider_id" : "1"
    },
    "simplelogin:2" : {
      "displayName" : "GI Jane",
      "provider" : "password",
      "provider_id" : "2"
    }
  },
  "todos" : {
    "simplelogin:1" : {
      "-JUAfv4_-ZUlH7JqM4WZ" : {
        "completed" : false,
        "done" : false,
        "group" : false,
        "private" : false,
        "subject" : "First"
      },
      "-JUAfveXP_sqqX32jCJS" : {
        "completed" : false,
        "done" : false,
        "group" : false,
        "private" : true,
        "subject" : "Second"
      },
      "-JUAfwXnMo6P53Qz6Fd2" : {
        "completed" : false,
        "done" : false,
        "group" : false,
        "private" : false,
        "subject" : "Third"
      }
    },
    "simplelogin:2" : {
      "-JUAg9rVemiNQykfvvHs" : {
        "completed" : false,
        "done" : false,
        "group" : false,
        "private" : false,
        "subject" : "Q first"
      },
      "-JUAgAmgPwZLPr2iH1Ho" : {
        "completed" : false,
        "done" : false,
        "group" : false,
        "private" : false,
        "subject" : "Q second"
      },
      "-JUAgBfF8f7V5R5-XgrY" : {
        "completed" : false,
        "done" : false,
        "group" : false,
        "private" : true,
        "subject" : "Q third"
      }
    }
  }
}

我想查询 todos 以获取带有private:true 的所有记录。这可能使用firebase(angularfire)吗?我应该怎么做?或者我应该更多地去规范化并安排路径 /private 以避免走下 todos ?

【问题讨论】:

  • Firebase 可以根据节点的名称或节点的优先级来查询数据。如果您的private 属性不是这两者,则您必须将其提升为此类(例如,通过为每个节点调用setPriority 并使用private 的值),或者您必须提供一个索引来提供按值列出的数据列表(例如,具有所有非私有待办事项名称的节点)。请参阅firebase.com/blog/2013-04-12-denormalizing-is-normal.htmlfirebase.com/blog/2013-10-01-queries-part-one.htmlfirebase.com/blog/2014-01-02-queries-part-two.html
  • 谢谢你的回答,我明白了。
  • 嗨@Denis,我下面的解决方案应该适合你。我将您的 JSON 导入 Firebase 进行检查。不知道为什么没有人提到这一点。如果您能为未来登陆这里的人(比如我)更新答案,那就太好了。
  • 也许 .orderByChild 在 2014 年不可用,但它肯定在 2020 年可用,并且可以正常工作。谢谢马特!

标签: json firebase angularfire


【解决方案1】:

假设你有 uid,这应该很简单:

var uid = "simplelogin:1";
var todosRef = new Firebase("https://yourdb.firebaseio.com/todos/" + uid);
var privateTodosRef = todosRef.orderByChild("private").equalTo(true);
var privateTodos;

privateTodosRef.on("value", function(response) {
  privateTodos = response.val();
});

这应该返回一个包含该用户所有私人待办事项的对象,由他们的待办事项键组织(即"-JUAfv4_-ZUlH7JqM4WZ"。如果您想使用 Angularfire,您可以将其包装在 $firebaseArray 中并按如下方式分配它:

$scope.privateTodos = $firebaseArray(privateTodosRef);

这里是a reference,了解有关复杂查询的更多信息,正如其他回复中提到的,有一些很好的优化可以通过优先级和重组来完成。

编码愉快!

【讨论】:

  • 这正是 TS(和我)所寻找的。请投票,因为这应该是正确的答案!
  • 实际上,如果找到过滤数据,这是唯一的方法。从语义上讲,它并不一致,因为语法中没有关于过滤的符号。我认为 Firebase 目前还缺乏很多真实的文字功能。一开始就考虑所有可能的查询情况来构建复杂的数据结构是不现实的。
  • 您可能还需要在数据库规则firebase.google.com/docs/database/security/indexing-data中添加一个indexOn字段@
【解决方案2】:

Firebase 中没有 WHERE 子句。查看this thread 了解有关按多个字段进行搜索的一些重要结构提示、this thread 用于数据库样式查询、this blog 用于查询以及the docs

您的第一种方法应该是对数据进行分段,如何回读。类似于以下内容:

/todos/public
/todos/private
/todos/completed

您也可以按照文档中的说明utilize priorities。然后根据优先级获取项目。

如果列表少于一千,如果数据正确分区应该是这样,您可能只需获取待办事项列表并在客户端过滤它 - 像这样的短集合的一个很好的选择,特别是使用 Angular 等出色的绑定库时。

【讨论】:

  • 感谢 Kato 的回答和线程链接。是的,我正在使用 Angular,我也计划使用您的辅助实用程序。我知道我可以像数组一样抓取所有列表并过滤它,如果不是太大的话。我不想只专注于某一点,但也尝试找出其他方法。
【解决方案3】:

Firebaase 中的所有数据都可以通过 URL 访问。 如果您转到 Firebase 仪表板查看您的数据模型 (Forge) 并单击您感兴趣的属性,您将被重定向到一个 URL,您可以通过该 URL 访问此特定数据,例如https://myapp.firebaseio.com/todos/simplelogin:1/-JUAg9rVemiNQykfvvHs/private。记住这一点,您可以使用 AngularFire 访问这些数据。

【讨论】:

  • 谢谢你,亚历克斯的回答。是的,我认为在你的回答之后,Katos and Franks 回答,我对下一个研究以及如何考虑非规范化有了很好的概述。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-11
  • 1970-01-01
  • 2011-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多