I am using nativescript-plugin-firebase to query firebase database in my angular2-nativescript application. I went through the documentation on how to query the database by field. For example I would like to fetch address of a user, based on uid for the below example database. But I could not find a way. Any help will be appreciated.
{
"address" : {
"-KfBtEuTA43UzSFfK7kU" : {
"house_number" : "hno1",
"street" : "street1",
"city" : "city1",
"uid" : "0P3Km5i9cEd1Akg7gJfJnALUSZw2"
},
"-KfC4Myo69bTZQCzw1yz" : {
"house_number" : "hno2",
"street" : "street2",
"city" : "city2",
"uid" : "4sj3ADekxsVNf5RaAFjbLbF6x0K2"
}
}
}
The following code gave me the query result by uid.
firebase.query(result => {
console.log("query result:", JSON.stringify(result));
}, "/address", {
orderBy: {
type: firebase.QueryOrderByType.CHILD,
value: 'uid'
},
ranges: [
{
type: firebase.QueryRangeType.START_AT,
value: uidValue
},
{
type: firebase.QueryRangeType.END_AT,
value: uidValue
}
]
})
Related
I am trying to write a firebase rule that checks to see if you have access to a child of one node by checking the data of another node. The issue I am having is accessing the other node's data because it is stored under an AutoId. How would I access the data under the AutoId?
Here is my database structure:
{
"products" : {
"Product001" : {
"ownerId" : "User002",
"productName": "Name"
},
"product002" : {
"ownerId" : "User001",
"productName": "Name"
}
},
"shares" : {
"share001" : {
"accepted" : true,
"ownerId" : "User002",
"productId" : "Product001",
"userEmail" : "example#email.com"
},
"share002" : {
"accepted" : true,
"ownerId" : "User001",
"productId" : "Product002",
"userEmail" : "email#exaple.com"
}
},
"users" : {
"User001" : {
"email" : "example#email.com",
"firstName" : "John",
"lastName" : "Smith"
},
"User002" : {
"email" : "email#example.com",
"firstName" : "John",
"lastName" : "Smith"
}
}
}
Here is the section of the rules that is causing me a problem:
"products":{
"$productId":{
".read":"root.child('shares').child($shareId).child('productId').val() === $productId && root.child('shares').child($shareId).child('ownerId').val() === auth.uid",
".write":"root.child('shares').child($shareId).child('productId').val() === $productId && root.child('shares').child($shareId).child('ownerId').val() === auth.uid"
}
}
Essentially, a user is only allowed to access a premises if they are in a share that contains their information.
Thank you for any advice.
There is no way in security rules to query or search another node, as the performance of that would be way too unreliable. So in your current data model it is not possible to allow the user access to a product if they have any shares for that product.
You'll need to have a list somewhere in a knowable path of the products the user can read. For example, say that you keep a list of the products the user is interested in:
"interests" : {
"User001" : {
"Product001": true,
"Product002": true
},
Now you can allow the user access to all products they follow with:
"products":{
"$productId":{
".read":"root.child('interests').child(auth.uid).child($productId).exists()",
".write": ...
}
}
The data in the realtime db is structure like below:
"orders" : {
"-LM5p4tl7Og_PMJOspZ-" : {
"customer" : {
"_name" : "Vik Kumar",
"_uid" : "oSEYj0zrkhPCk9r7uwyOOkHcqe53"
},
"order" : {
"_orderNumber" : "VikKumar-26954",
"_orderStatus" : "Pending",
"_orderTotal" : 500,
}
},
"-LM5s1wRCvqWA1vsZONy" : {
"customer" : {
"_name" : "Vik Kumar",
"_uid" : "oSEYj0zrkhPCk9r7uwyOOkHcqe53"
},
"order" : {
"_orderNumber" : "VikKumar-11423",
"_orderStatus" : "Pending",
"_orderTotal" : 500,
}
},
"-LM5sOHzjLeqFGFleMxq" : {
"customer" : {
"_name" : "Vik Kumar",
"_uid" : "oSEYj0zrkhPCk9r7uwyOOkHcqe53"
},
"order" : {
"_orderNumber" : "VikKumar-63772",
"_orderStatus" : "Pending",
"_orderTotal" : 500,
}
}
}
I am using angularfire2 in my ionic app and filtering few orders as below:
getPendingOrders(dateStr:string){
return new Promise((resolve, reject) =>
{
this.db.list('orders',
ref => ref.orderByChild("order/_date").equalTo(dateStr)
).valueChanges().subscribe(
res => {
resolve(res)
},
err => {
console.log(err)
reject(err)
}
)
})
}
The above query gives me the response as below
[{"customer": {}, "order": {}}, {"customer": {}, "order": {}}]
I can render it in UI just fine and i want the end user to be able to update the value of property "_orderStatus". The trouble is the way i queried the data i have lost the keys to identify a particular object to update it. Please advise
ok, not sure if this helps,I think you have migrated to use AngularFire 5.0. Calling .valueChanges() will return an Observable without any metadata (item key for example), you need to use .snapshotChanges() call instead:
this.db.list(...)
.snapshotChanges()
.map(changes => {
return changes.map(change => ({key: change.payload.key, ...change.payload.val()}));
})
.subscribe(...)
My firebase database structure is as below. I would like to search with a particular "Info/Email", let's say "abc#abc.com".
{
"-KhWrBcYyMluJbK7QpnK" : {
"Info" : {
"Email" : "xyz#gmail.com"
},
"Settings" : {
"Status" : "Accepted"
}
},
"-KhX0tgQvDtDYqt4XRoL" : {
"Info" : {
"Email" : "abc#abc.com"
},
"Settings" : {
"Status" : "Accepted"
}
},
"-KhX1eo7uFnOxqncDXQ5" : {
"Info" : {
"Email" : "abc#abc.com"
},
"Settings" : {
"Status" : "Pending"
}
}
}
I added a rule too
"Invitation" : {
".indexOn": ["Info/Email","Settings/Status"]
}
My AngularFire code is as follows:
var rootRef = firebase.database().ref().child('Invitation');
var userInvitations = rootRef.child("Info").orderByChild("Email").equalTo("abc#abc.com");
var allInvitations = $firebaseArray(userInvitations);
But I am getting a FIREBASE WARNING: Using an unspecified index. Consider adding ".indexOn": "Email" at /Invitation/Info to your security rules for better performance. and of course I am not receiving any data.
What are the mistakes I made here? Also can I add multiple orderByChild, for example: if I want to find details of the record, which has "Info/Email" equal to "abc#abc.com" and "Settings/Status" equal to "Pending" ?
The Firebase API only allows you to filter children one level deep
So with reference to your data structure:
if it were to be this way,
{
"-KhWrBcYyMluJbK7QpnK" : {
"Email" : "xyz#gmail.com",
"Settings" : {
"Status" : "Accepted"
}
},
"-KhX0tgQvDtDYqt4XRoL" : {
"Email" : "abc#abc.com",
"Settings" : {
"Status" : "Accepted"
}
},
"-KhX1eo7uFnOxqncDXQ5" : {
"Email" : "abc#abc.com",
"Settings" : {
"Status" : "Pending"
}
}
}
You should write your rules this way instead.
"Invitation" : {
"Info" : {
".indexOn": "Email",
},
"Settings" : {
".indexOn": "Status",
}
}
Then you will be able to query the data
var allInvitations = [];
var rootRef = firebase.database().ref().child('Invitation');
var userInvitations = rootRef.orderByChild("Email").equalTo("abc#abc.com");
userInvitations.on('value', snap => {
var invitations = snap.val()
for (prop in invitations ) {
allInvitations.push(invitations[prop ]);
}
console.log(allInvitations);
})
I have firebase database in this form.
"items":{
"-Jp9VLYBwENfNVLKYyCG" : {
"-Jp9VMKkTUggcMrUCO8S" : {
"author" : "facebook:#########",
"created" : 1431474107638,
},
"-Jp9VobJP0qbSbbEdyW0" : {
"author" : "facebook:#########",
"created" : 1431474227548
}
},
"-JpEbifKeRj-_H7TWhQ2" : {
"-JpEbrnT6SFRFc6U_HWX" : {
"author" : "facebook:#########",
"created" : 1431559961683
},
"-JpEby5mZuQMsU-9YCpk" : {
"author" : "facebook:##########",
"created" : 1431559987495
}
}
}
I want to add the following object to each $id containing author and created key-value pairs.
upVote: {
active: true,
total: 0
},
downVote: {
active: true,
total: 0
}
I am first trying to fetch the values using DataSnapshot. But it doesn't print the keys in console. What is wrong here?
var ref = new Firebase(FBURL + "/items");
ref.once("value", function(snapshot) {
console.log("snapshot key: " + snapshot.key());
snapshot.forEach(function(childSnapshot){
var key = childSnapshot.key();
var val = childSnapshot.val();
console.log("child snapshot key: " + key);
childSnapshot.forEach(function(deepSnap){
console.log("deep shot key: " + deepSnap.key());
});
});
});
RESOLVED The problem was that I had some security rules set up with read and write permissions. Therefore wasn't allowing me to read the element from the user scope that I was calling the script. It was one gotcha like problems.
After this step, it was easy to update the database with values:
var deepRef = ref.child(key).child(deepSnap.key());
deepRef.update({upVote: {
active: true,
total: 0
},downVote: {
active: true,
total: 0
}});
I am using accounts-google package to register users
I have multiple users stored in mongo
db.users.find()
{ "_id" : "av8Dxwkf5BC59fzQN", "profile" : { "avatar" : "https://lh3.googleusercontent.com/-rREuhQEDLDY/AAAAAAAAAAI/AAAAAAAADNs/x764bovDfQo/photo.jpg", "email" : "lfender6445#gmail.com", "name" : "Luke Fender", "room" : "2" }, "services" : { "resume" : { "loginTokens" : [ { "when" : ISODate("2014-04-26T19:34:52.195Z"), "hashedToken" : "8na48dlKQdTnmPEvvxBrWOm3FQcWFnDE0VnGfL4hlhM=" } ] } } }
{ "_id" : "6YJKb7umMs2ycHCPx", "profile" : { "avatar" : "https://lh3.googleusercontent.com/-rREuhQEDLDY/AAAAAAAAAAI/AAAAAAAADNs/x764bovDfQo/photo.jpg", "email" : "lfender6445#gmail.com", "name" : "Luke Fender", "room" : "2" }, "services" : { "resume" : { "loginTokens" : [ { "when" : ISODate("2014-04-26T19:35:00.185Z"), "hashedToken" : "d/vnEQMRlc4VI8pXcYmBvB+MqQLAFfAKsKksjCXapfM=" } ] } } }
But Meteor.users.find().fetch() returns document for logged in user only - shouldn't this return entire collection? Are the other users somehow private by default?
This is the default behaviour. You can only see who you're logged in as.
You can make a custom publish function to publish a custom subset/what you want. In the example below I publish all the users (only the profile field)
Server side code
Meteor.publish('users', function() {
return Meteor.users.find({}, {fields:{profile: true}});
});
Client side code
Meteor.subscribe("users");
You might want to alter these to only publish what is relevant to the user. If you have over 100 users this begins to get wasteful to publish all of them to the client.