Firebase:如何从存在特定键的数据中检索记录? [英] Firebase: How do I retrieve records from my data for which a specific key exists?
问题描述
我在 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
的参数添加到具有 creation
的 company
的子代,并通过该参数进行查询.
数据
- 查询将是
var ref = new Firebase(fbUrl+'/companies').orderByChild("hasCreation").equalTo(hasCreation);
- 如果查询中的
hasCreation
为null
,则查询将返回没有hasCreation
子项的公司. - 如果查询中的
hasCreation
为true
,则查询将返回具有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 isnull
, the query will return the companies without ahasCreation
child. - If
hasCreation
in the query istrue
, the query will return the companies withhasCreation===true
.
- If
{
"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屋!