Firebase:如何从存储特定密钥的数据中检索记录?

时间:2015-03-21 04:56:53

标签: javascript angularjs firebase angularfire

我在firebase中的数据如下所示:

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

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

      "facebook": {
      },

      "apple": {
      }
    }
  }
}

companies键下有数万条记录。我如何有效地执行以下查询?

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

如何只查询名称中没有密钥creation的记录?

我还想在返回的结果集上调用.on('child_added'),以便稍后我只能处理这些特定的记录。有可能吗?

2 个答案:

答案 0 :(得分:11)

编辑:不使用额外参数的简单方法

查询

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

  • 找到没有 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的存在,将creation的子项分成两个分区可能是值得的。这样,您可以单独阅读这两个细分,而无需依赖查询。

工厂

以下是修改过的工厂的样子(我已修改PLNKR以匹配):

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;
  }
});

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



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

(保留此内容供参考)

另一种方法是向hasCreation的{​​{1}}子项添加另一个名为companies的参数,并对其进行查询。

数据

  • 然后查询为creation
    • 如果查询中的var ref = new Firebase(fbUrl+'/companies').orderByChild("hasCreation").equalTo(hasCreation);hasCreation,则查询将返回没有null孩子的公司。
    • 如果查询中的hasCreationhasCreation,则查询将返回true的公司。
hasCreation===true

规则

您可以将{ "company1" : { "creation" : { "name" : "company1" }, "hasCreation" : true }, "company2" : { "name" : "company2" }, "company3" : { "name" : "company3" }, "company4" : { "creation" : { "name" : "company4" }, "hasCreation" : true } } 添加到规则中,如下所示:

".indexOn" : "hasCreation"

公司工厂

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

控制器

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;
  }
});

HTML

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;
   });
 }
});

答案 1 :(得分:0)

我会做什么,是否会设置条件来验证您的xxx.firebaseio.com/Application/companies/______/creation是否存在。在一个空白的空白处,您可以设置for循环以激怒公司阵列。然后,您可以使用angular.forEach创建两个阵列:一个包括那些有创建'和另一个阵列的公司其中的元素不包括“创作”。

希望有所帮助:)

编辑:
在这个主题中还有另一种解决这个问题的方法:
Angularfire: how to query the values of a specific key in an array?