I have a database containing a structure similar to the one shown below. Since I am not allowed to make it public I am using the following keys:
i = {0,1,2,3....}
All a(i) represent single key/value pairings e.g. userName: "awesome"
With the below structure, every time a User wants to create new Stuff these are the steps I currently take
Store images to FIRStorage and retrieve their respective downloadURL
Then I add the Stuff to FIRDatabase. At this point I add all of the info related to a(i) because they're all under a single child; Stuff.UUID, hence I send one huge dictionary consisting of the data.
The issue arises in adding data to the mini-dictionaries. Because they are in different paths, I have to individually make requests to all of them as shown below
I then add location info
Followed by the respective child of timeStamp
The images information is next to be updated
Subscribe the User to respective Stuff.UUID
Lastly add the User.UUID to the members portion of Stuff
Is it possible to reduce steps 3-7?
As a follow up, is it possible to add values into different paths with one call?
PS: Link to what the code of the above demo might look like. Due to confidentiality stuff I am not allowed to post the actual code.
{
"Users":
{
"JglJnGDXcqLq6m844pZ":
{
a(0),
a(1),
a(2),
a(3),
a(4),
a(5),
"Stuff":
{
"fcWpzduhpPn8XR6Zqca": true,
"gfntTr6TkDwZ439jkW8": true
}
}
},
"Stuff":
{
"fcWpzduhpPn8XR6Zqca":
{
a(0),
a(1),
a(2),
a(3),
a(4),
a(5),
a(6),
a(7),
"location":
{
"latitude":"-17.41439",
"longitude":"-5.85170"
},
"timestamp":
{
"created":
{
a(0),
a(1),
a(2),
a(3),
a(4),
a(5),
},
"lastModified":
{
a(0),
a(1),
a(2),
a(3),
a(4),
a(5),
}
},
"images":
{
"B4FaR6wfJAeXqJ29T33":
{
"imageURL": "https://google.com"
}
},
"members":
{
"JglJnGDXcqLq6m844pZ": true,
"DpHAfrqL4eqbR8QNgHg": true
}
}
}
}
Related
I want to add links to some related entities and collection, without all property data in one response, only the Link.
For unterstanding I structure the Question in some parts
Simple example of data Model
Order
Order->AddressFrom (Entity)
Order->PackageItems (Collection)
Which is the wright HAETOAS way to generate links or how to name entities in response.
First question: How to link address, double in entity name and links part and how to nam?
{
"_embedded":{
"orders":[
{
"id":"id",
"addressLinkFrom":{
"href":"link"
},
"_links":{
"self":{
"href":"link"
},
"addressFrom":{
"href":"d"
}
}
}
]
}
}
or
"addressFrom":{
"href":"link"
},
"_links":{
...
}
or
or
"addressFrom":{
"self":{
"href":"link"
}
},
"_links":{
...
}
Second: How to link collection to specific and not all entities
{
"_embedded":{
"orders":[
{
"id":"id",
"packageItemIds":[
{
"href":"link"
},
{
"href":"link"
}
]
}
]
}
}
or
"packageItemIds":[
{
"self:"{
"href":"link"
}
}]
Third: How is the right format for (update, post), which I have to parse, like the address, where I'm sending the ID or like the packageItems, where I sending the link.
{
"id":"id",
"addressFrom":{
"id":"12345"
}
"packageItems":[
{
"href":"link"
},
{
"href":"link"
}
]
}
For your information, as frontend Client I'm using lagoshny /
ngx-hateoas-client,
when someone has their extra information beside the HAETOAS standard, how is the best way, please tell me.
Thanks for your help.I want to add links to some related entities and collection, without all data in one response.
I'm currently learning Firebase/NoSQL database modeling. I just ended watching the Firebase for SQL developers, but I still have few doubts.
Let's say I'm creating Instagram-styled app where users could share their photos and each user could like each photo.
So I would like to achieve two things:
1. Know which user has liked which photo. (So only one like per user for photo)
2. How many likes each photo has.
My current database looks like this:
{
"images": {
"100": {
"imageUrl": "../../image.png",
},
"101": {
"imageUrl": "../../image.png",
}
},
"users": {
"200": {
"name": "user1"
},
"201": {
"name": "user2"
}
},
"likes": {
"100": 1,
"101": 2
},
"likesPerUser": {
"200": {
"100": "true"
},
"201": {
"100": "true",
"101": "true"
}
}
"imagesPerUser": {
"200": {
"101": "true"
},
"201": {
"100": "true"
}
}
My question is related to the counter, that counts how many likes each photo has. Would the best practice be that I have them as their own "root"-object (current model) OR to create key-value pair for "likes" under the photo (and maybe do the same for authorID)?
This Firebase Sample recommends having the counter(likes_count) under each post. And also having a node(likes) with a list/lookup . Like this:
"images": {
"100": {
"imageUrl": "../../image.png",
"likes_count":2,
"likes":{
"200":true,
"201":true
}
},
"101": {
"imageUrl": "../../image.png",
"likes_count":1,
"likes":{
"201":true
}
}
}
This way you'll ensure only one like per user, because keys must be unique under a Firebase Realtime Database node, and the user ids are used as keys under the likes_count node. You can also know which users liked the photo because their uids are there. And obviously, you can see how many likes a photo has by accessing the counter.
I am working to calculate the difference between two times in ionic.
I am using AngularFire and my tree looks like this:
{
"users": {
"name": {
"17": {
"10": {
"2017": {
"-Kwfm1k9_A74PzlmijUJ": {
"date": "17/10/2017",
"hora": "17:20:58",
"status": "In"
},
"-Kwfm8wEJ8Oob4YFvNNu": {
"date": "17/10/2017",
"hora": "17:21:27",
"status": "Out"
},
"-KwfoKkPJMt2g8AQNmxq": {
"date": "17/10/2017",
"hora": "17:31:00",
"status": "In"
},
"-Kwfp0BOAGnM-2_MfziP": {
"date": "17/10/2017",
"hora": "17:33:58",
"status": "Out"
},
"-KwfqW5XKpUNedda4rZz": {
"date": "17/10/2017",
"hora": "17:40:31",
"status": "In"
},
"-Kwg0pQDlI3FMV3BPNaa": {
"date": "17/10/2017",
"hora": "18:29:58",
"status": "Out"
}
}
}
}
}
}
}
I would like to get a difference between the first and second, third and fourth, fifth and sixth, remembering that they are related by the tag "Status".
First In - Out = difference
Second In - Out = difference
Third In - Out = difference
Always doing the difference between the In's and Out's.
In's are for when a person come in the room. Out's are for when a person come out of the room. I want to record the time a person spend inside of a room.
So the results would be:
"17:20:58" - "17:21:27" = 00:01:29
"17:31:00" - "17:33:58" = 00:02:58
"17:40:31" - "18:29:58" = 00:49:27
Do you have any tip on refactoring this code so it works fine?
Remembering I'm using Ionic 3 with AngularFire4
Appreciate the help.
To achieve your goal I recommend you to restructure your data. For now, there is no real relation between the IN's and OUT's.
A possible approach would be to create some node which wraps the checkIn and the checkOut. Let's call it session. Each time a user checks in a new session get's created and each time a user checks out a session get's closed.
Your structure could look similar to this:
"sessions": {
"uid": { // or name or whatever
"17-10-2017": { // not sure if you need the date in the structure, but if you need it make a single node like this
"-Kwfm1k9_A74PzlmijUJ": { // this is a session create it on each check in
"checkin": 1508354574, // timestamp
"checkout": 1508354584
},
}
}
}
Here's a code example (just to give you an idea how it could look like):
var ref = firebase.database().ref("sessions/uid"); // uid must be dynamic
// checkin
ref.push({
checkin: firebase.database.ServerValue.TIMESTAMP // make sure to use the servers timestamp
}); // creates a new session with a pushkey as id
// checkout
ref.child('sessionId').update({
checkout: firebase.database.ServerValue.TIMESTAMP
});
// stats
ref.child('sessionId').once('value', function(snap) {
var session = snap.val();
var difference = session.checkout - session.checkin;
// now you have the difference in milliseconds or seconds depending on your timestamp format. this can be formatted whatever unit you want e.g. minutes, hours...
});
Hope this gives you an idea, how it could be done.
I'm working on setting up validaton rules for a Firebase data structure, created using the Bolt compiler.
I'm currently having the Bolt statement below:
path /sharedEvents/{share} is Boolean[] {
read() { isMailOfCurrentUser( share ) }
create() { isOwnerOfEvent( ...) } //NOT YET CORRECT!
delete() { isOwnerOfEvent( prior(...) } //NOT YET CORRECT!
}
With this, I'm trying to achieve that:
Only users having a mail corresponding to the key of 'share' are allowed to read the data (they use this date to retrieve the key of events shared with them.
Only the owner of an event is able to add/remove the key for his event to the list of shared events.
This second point is where I'm running into trouble -I'm not able to create the create/delete rules- since I have no idea how to reference the keys of the boolean values in the validation rule...
Example data in Firebase for the above bolt statement:
sharedEvents
ZW5kc3dhc0BldmVyeW1hMWwuYml6
-BDKBEvy-hssDhKqVF5w: true
-FDKBEvy-hsDsgsdsf5w: true
-ADBEvy-hfsdsdKqVF5w: true
aXQnc251bWJlcnNAbWExbDJ1LnVz
-KBEvy-hsDhH6OKqVF5w: true
To clarify the needs on this example:
Only user with mail 'ZW5kc3dhc0BldmVyeW1hMWwuYml6' is able to read the three nested childs.
Only the owner of event '-BDKBEvy-hssDhKqVF5w' should be able to create/delete this value. (the same for the other event key/boolean pairs).
My question: is this setup going to work (and how to setup the create/delete rules)? Or is this not going to work and should I rethink/structure the data?
Any help is appreciated!
-----------------OUTPUT JSON FILE------------------------------------------
The question above has been answered, this section is showing the resulting json
"sharedEvents": {
"$share": {
".read": "<removed for readability>",
"$event": {
".validate": "newData.isBoolean()",
".write": "<removed for readability>"
}
}
},
Thanks again for your quick support!
You'll need a nested path statement to handle the restriction on the events (the nodes under /sharedEvents/$mail/$eventid). I quickly prototyped with this JSON structure:
{
"events": {
"-ADBEvy-hfsdsdKqVF5w": {
"name": "Event 1",
"ownerMail": "aXQnc251bWJlcnNAbWExbDJ1LnVz"
},
"-BDKBEvy-hssDhKqVF5w": {
"name": "Event 2",
"ownerMail": "aXQnc251bWJlcnNAbWExbDJ1LnVz"
},
"-FDKBEvy-hsDsgsdsf5w": {
"name": "Event 3",
"ownerMail": "aXQnc251bWJlcnNAbWExbDJ1LnVz"
},
"-KBEvy-hsDhH6OKqVF5w": {
"name": "Event 3",
"ownerMail": "ZW5kc3dhc0BldmVyeW1hMWwuYml6"
}
},
"sharedEvents": {
"ZW5kc3dhc0BldmVyeW1hMWwuYml6": {
"-ADBEvy-hfsdsdKqVF5w": true,
"-BDKBEvy-hssDhKqVF5w": true,
"-FDKBEvy-hsDsgsdsf5w": true
},
"aXQnc251bWJlcnNAbWExbDJ1LnVz": {
"-KBEvy-hsDhH6OKqVF5w": true
}
},
"userMails": {
"peter": "aXQnc251bWJlcnNAbWExbDJ1LnVz",
"puf": "ZW5kc3dhc0BldmVyeW1hMWwuYml6"
}
}
And came up with these rules:
path /sharedEvents/{share} {
read() { isMailOfCurrentUser(share) }
}
path /sharedEvents/{share}/{event} is Boolean {
create() { isOwnerOfEvent(event) }
delete() { isOwnerOfEvent(prior(event)) }
}
isMailOfCurrentUser(share) { true }
getMailOfCurrentUser(uid) { root.ownerMails.uid }
getEventOwnerMail(event) { root.events.event.ownerMail }
isOwnerOfEvent(event) { getMailOfCurrentUser(auth.uid) == getEventOwnerMail(event) }
Ignoring any mistakes on my end, this should be the basics of the authorization structure you're looking for.
I'm building an app where I need to process 5k+ tasks in small batches. For that I have a queue of tasks that is stored in a Firebase. I'd like to be able to pull certain amount of tasks with empty status, update their status and write back.
Currently I don't see how I can pull data where a certain field is empty. Is it possible? If not, what would be the alternative solution?
UPDATED 02/12. Here is the data structure that I have:
{
"-KAMnc89C5Yi_ef18ewc" : {
"0": {
"url": "https://excample.com/url",
"status": "done"
},
"1": {
"url": "https://excample.com/url1"
},
"2": {
"url": "https://excample.com/ur2"
},
"3": {
"url": "https://excample.com/ur3"
}
}
And this is the query I'm using:
queueRef.orderByChild('status').equalTo(null).limitToFirst(1).once('value', function(snapshot) {
console.log(snapshot.val());
});
queueRef points to "-KAMnc89C5Yi_ef18ewc" from the data above.
I expect to get one object - "1", but instead I'm getting all of them. Is there something I'm missing?
Firebase doesn't allow you to store a property without a value. That simply means that the property doesn't exist.
Luckily this doesn't really matter too much, because this seems to work. Given this data structure:
{
"-KADbswYg3FiQF78mmUf": {
"name": "task1",
"status": "done"
},
"-KADbugr7QzTx0s93Fs0": {
"name": "task2"
},
"-KADbvKvBgiAXxnQvoBp": {
"name": "task3"
}
}
This works:
ref.orderByChild('status').equalTo(null).once('value', function(snapshot) {
console.log(snapshot.val());
})
This prints task2 and task3.
Use the DataSnapshot.exists()
This will returns true if this snapshot contains any data. If not it will return false. According to the documentation here. It is slightly more efficient than using snapshot.val() !== null.
With a data structure like this:
{
"girlfriend": {
"first": "Pamala",
"last": "Anderson"
}
}
And a firebase call like this:
var ref = new Firebase("https://myURL/girlfriend/Pamala");
ref.once("value", function(snapshot) {
var a = snapshot.exists();
// a === true
var b = snapshot.child("girlfriend").exists();
// b === true
var c = snapshot.child("girlfriend/first").exists();
// c === true
var d = snapshot.child("girlfriend/middle").exists();
// d === false (because there is no "name/middle" girlfriend in the data snapshot)
});