Firebase:如何从存在特定键的数据中检索记录? [英] Firebase: How do I retrieve records from my data for which a specific key exists?

查看:23
本文介绍了Firebase:如何从存在特定键的数据中检索记录?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 firebase 中有如下数据:

应用程序":{公司":{火力基地":{创造":{"name": "Firebase Inc","位置": "美国"},谷歌": {创作":{"name": "谷歌公司","位置": "美国"}}Facebook": {},苹果": {}}}}

companys 键下有数以万计的记录.我如何有效地执行以下查询?

如何仅查询其名称下存在键 creation 的记录?

如何仅查询名称下没有键 creation 的记录?

我还想在返回的结果集上调用 .on('child_ added') 以便我以后可以只处理那些特定的记录.可能吗?

解决方案

更简单的方法,无需使用额外参数

查询

以下是无需使用额外参数即可执行此操作的查询:

  • 查找没有creation的公司:
    • var ref = new Firebase(fbUrl+'/companies').orderByChild("creation").equalTo(null);
  • 查找具有creation的公司:
    • var ref = new Firebase(fbUrl+'/companies').orderByChild("creation").startAt(!null);
  • 您可以将 ".indexOn": "creation" 添加到规则中.

编辑 2: 我很好奇,所以我将 11,000 条记录推送到 /companies2(一半有 creation 孩子,一半没有).我能够使用上述查询(或我在下面显示的变体之一)在大约 4 秒内检索到 5500 条匹配记录.

编辑 3:如果您经常运行这些查询,根据 的存在将 /companies 的子项分成两个 bin 可能是值得的创建.这样,您就可以分别读取这两个段,而无需依赖查询.

工厂

这是修改后的工厂的样子(我修改了 PLNKR匹配):

app.factory("CompaniesFactory",function($q, fbUrl){返回函数(hasCreation){var deferred = $q.defer();var ref = new Firebase(fbUrl+'/companies').orderByChild("creation");无功查询;如果(hasCreation){查询 = ref.startAt(!null);//或者://查询 = ref.startAt(true);} 别的 {查询 = ref.equalTo(null);//或者://查询 = ref.endAt(!null);//查询 = ref.endAt(true);}查询.一次(值",函数(数据快照){deferred.resolve(dataSnapshot.val());}, 函数(错误){deferred.reject(error);});返回 deferred.promise;}});

是的,可以在返回的 dataSnapshot 上调用 .on('child_added').请参阅 DataSnapshot.ref().


<小时>

使用额外参数的原始答案:

(留作参考)

另一种方法是将另一个名为 hasCreation 的参数添加到具有 creationcompany 的子代,并通过该参数进行查询.

数据

  • 查询将是 var ref = new Firebase(fbUrl+'/companies').orderByChild("hasCreation").equalTo(hasCreation);
    • 如果查询中的 hasCreationnull,则查询将返回没有 hasCreation 子项的公司.
    • 如果查询中的 hasCreationtrue,则查询将返回具有 hasCreation===true 的公司.

{公司 1":{创造":{名称":公司1"},hasCreation":真},公司 2":{名称":公司 2"},公司 3":{名称":公司 3"},公司4":{创造":{名称":公司4"},hasCreation":真}}

规则

您可以将 ".indexOn" : "hasCreation" 添加到您的规则中,如下所示:

 "so:29179389":{.read":真的,.write":真的,公司":{".indexOn" : "hasCreation"}}

公司工厂

app.factory("CompaniesFactory",function($q, fbUrl){返回函数(hasCreation){var deferred = $q.defer();如果(!hasCreation){hasCreation = null;}var ref = new Firebase(fbUrl+'/companies').orderByChild("hasCreation").equalTo(hasCreation);ref.once(值",函数(数据快照){deferred.resolve(dataSnapshot.val());});返回 deferred.promise;}});

控制器

app.controller('HomeController',function($scope,fbUrl,CompaniesFactory) {$scope.getCompanies = 函数(hasCreation){var company = new CompaniesFactory(hasCreation).then(function(data){控制台日志(数据);$scope.companys = 数据;});}});

HTML

<div ng-controller="HomeController"><button ng-click="getCompanies(true)">使用创建查找</button><button ng-click="getCompanies(false)">查找而不创建</button><h2>公司:</h2>{{公司}}

I have data in firebase that looks like this:

"application": {
  "companies": {
    "firebase": {
      "creation": {
        "name": "Firebase Inc",
        "location": "USA"
      },

      "google": {
        "creattion": {
          "name": "Google Inc",
          "location": "USA"
        }
      }

      "facebook": {
      },

      "apple": {
      }
    }
  }
}

There are tens of thousands of records under companies key. How do i efficiently execute following queries?

How do I query only the records for which key creation is present under their name?

How do I query only the records that DO NOT have key creation present under their name?

I also want to call .on('child_added') on the returned result set so that I can process only those specific records later on. Is it possible?

解决方案

EDIT: Simpler way without using an extra parameter

Queries

Here are the queries to do this without having to use an extra parameter:

  • Find the companies without creation:
    • var ref = new Firebase(fbUrl+'/companies').orderByChild("creation").equalTo(null);
  • Find the companies with creation:
    • var ref = new Firebase(fbUrl+'/companies').orderByChild("creation").startAt(!null);
  • You would add ".indexOn": "creation" to the rules.

Edit 2: I was curious, so I pushed 11,000 records to /companies2 (half with creation children, half without). I was able to retrieve 5500 matching records in ~4 seconds using the above queries (or one of the variants I've shown below).

Edit 3: If you're running these queries frequently, it might be worth it to separate children of /companies into two bins based the presence of creation. That way, you can read the two segments separately without having to rely on queries.

Factory

Here is what the revised factory would look like (I've revised the PLNKR to match):

app.factory("CompaniesFactory",function($q, fbUrl){
  return function(hasCreation){
    var deferred = $q.defer();
    var ref = new Firebase(fbUrl+'/companies').orderByChild("creation");
    var query;
    if (hasCreation) {
      query = ref.startAt(!null);
      // or: 
      // query = ref.startAt(true);
    } else {
      query = ref.equalTo(null);
      // or:
      // query = ref.endAt(!null);
      // query = ref.endAt(true);
    }
    query.once("value", function(dataSnapshot){
      deferred.resolve(dataSnapshot.val());
    }, function (error) {
      deferred.reject(error);
    });
    return deferred.promise;
  }
});

And yes, it is possible to call .on('child_added') on the returned dataSnapshot. See DataSnapshot.ref().



Original answer using an extra parameter:

(Keeping this for reference)

Another way to do it would be by adding another parameter called hasCreation to children of companies that have creation, and query by that.

Data

  • The query would then be var ref = new Firebase(fbUrl+'/companies').orderByChild("hasCreation").equalTo(hasCreation);
    • If hasCreation in the query is null, the query will return the companies without a hasCreation child.
    • If hasCreation in the query is true, the query will return the companies with hasCreation===true.

{
  "company1" : {
    "creation" : {
      "name" : "company1"
    },
    "hasCreation" : true
  },
  "company2" : {
    "name" : "company2"
  },
  "company3" : {
    "name" : "company3"
  },
  "company4" : {
    "creation" : {
      "name" : "company4"
    },
    "hasCreation" : true
  }
}

Rules

You would add the ".indexOn" : "hasCreation" to your rules like so:

  "so:29179389":{
    ".read" : true,
    ".write" : true,
    "companies" : {
      ".indexOn" : "hasCreation"
    }
  }

Companies Factory

app.factory("CompaniesFactory",function($q, fbUrl){
  return function(hasCreation){
    var deferred = $q.defer();
    if (!hasCreation) {
      hasCreation = null;
    }
    var ref = new Firebase(fbUrl+'/companies').orderByChild("hasCreation").equalTo(hasCreation);
    ref.once("value", function(dataSnapshot){
      deferred.resolve(dataSnapshot.val());
    });
    return deferred.promise;
  }
});

Controller

app.controller('HomeController',function($scope,fbUrl,CompaniesFactory) {
 $scope.getCompanies = function(hasCreation) {
  var companies = new CompaniesFactory(hasCreation).then(function(data){
     console.log(data);
     $scope.companies = data;
   });
 }
});

HTML

<body ng-app="sampleApp">
  <div ng-controller="HomeController">
    <button ng-click="getCompanies(true)">Find with creation</button>
    <button ng-click="getCompanies(false)">Find without creation</button>
    <h2>Companies:</h2>
    {{companies}}
  </div>
</body>

这篇关于Firebase:如何从存在特定键的数据中检索记录?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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