I'm just starting out with Firebase (moving across from MySQL) and, after reading many documents/watching tutorials I've tried to structure the database for my "Ebay/Gumtree style app". Are there any major issues with what I've gone with?
I've sort of tried to structure it around each screen on my app so that I'm not reading a whole load of data that isn't needed (I think this is the flat structure I should be going for?), however this had led to some duplication of data (specifically images).
Is this a good way to structure the database? I've taken a few tips from here:
Best way to structure my firebase database
{
"users": {
"user1": {
"email": "example#gmail.com",
"password": "********",
"first name": "Example",
"last name": "User",
"age": "45",
"gender": "Male",
"address": "XX1 9YY"
}
},
"upload image": {
"user1": {
"image1": { #path to image
"condition": "Like New",
"price": "£100",
"upload date": "10/10/2019",
"promoted": True,
"promoted expiry": "11/11/2019"
},
"image2": {
"condition": "New",
"price": "£250",
"upload date": "12/12/2019",
"promoted": False
},
"user2": {
"image1": {
"condition": "Used",
"price": "£50",
"upload date": "05/05/2019",
"promoted": True,
"promoted expiry": "06/06/2019"
}
},
"promoted images": { #max 50 images stored here
"user1": {
"image1": #This image is a duplicated of the image above
"condition": "Like New",
"price": "£100",
"upload date": "10/10/2019",
"promoted": True,
"promoted expiry": "11/11/2019"
},
"user2": {
"image1": { #This image is also a duplicate
"condition": "Used",
"price": "£50",
"upload date": "05/05/2019",
"promoted": True,
"promoted expiry": "06/06/2019"
}
},
"categories": {
"category1": {
"image1": { #This is the third location image1 is stored
"condition": "Used",
"price": "£50",
"upload date": "05/05/2019",
"promoted": True,
"promoted expiry": "06/06/2019"
},
"image2": {
"condition": "New",
"price": "£250",
"upload date": "12/12/2019",
"promoted": False
}
},
"reviews": {
"user1": {
"review1": {
"rating": 4,
"message": "delivered on time, thanks"
},
"review2": {
"rating": 5,
"message": "great product, delivered quickly"
},
}
"user2": {
"review1": {
"rating": 1,
"message": "terrible service, took ages to arrive and was faulty!"
},
},
},
},
}
Some questions/thoughts as to why I've done things so far:
Is it a good idea to have multiple copies of the same image as it would save going through 1000s of images. For example, if I didn't have "promoted images" but wanted to find all promoted images i'd have to search through the "upload image" section (which will have many many more images than the 50 in "promoted images"
Each "category" is a new screen that will load lots of images so I've tried to separate this section out, rather than having a master "category" that gets read everytim any of the pages load.
Thanks
Related
Created an Azure template with the Microsoft.Network.VirtualNetworkCombo type element. The new operation works fine. But two out of three existing Virtual Networks when selected show "Loading..." in each of the subnet dropdowns.
Screen snapshot
I cannot figure out why 2 of 3 existing Virtual Networks get stuck in the "Loading..." state. Does anyone know what would exhibit this behavior?
Update
It has something to do with adding IPv6 address space (10:8:2::/64). Virtual Networks/subnets without IPv6 address space display fine.
Perhaps it is something to do with the constraints minAddressPrefixSize "/29" specifications for the subnets?
I sure hope the answer isn't IPv6 is not supported...
I have tested in my environment it is working fine for me.
in createUiDefinition.json i have passed the below code in "steps": [ ]
{
"name": "NetoworkConfig",
"label": "NetworkSettings",
"subLabel": {
"preValidation": "Configure the storage settings",
"postValidation": "Done"
},
"bladeTitle": "Networking",
"elements": [
{
"name": "Configure Vnet Settings",
"type": "Microsoft.Network.VirtualNetworkCombo",
"label": {
"virtualNetwork": "Virtual network",
"subnets": "Subnets"
},
"toolTip": {
"virtualNetwork": "",
"subnets": ""
},
"defaultValue": {
"addressPrefixSize": "/16"
},
"constraints": {
"minAddressPrefixSize": "/16"
},
"options": {
"hideExisting": false
},
"subnets": {
"subnet1": {
"label": "First subnet",
"defaultValue": {
"addressPrefixSize": "/24"
},
"constraints": {
"minAddressPrefixSize": "/24",
"minAddressCount": 12,
"requireContiguousAddresses": true
}
},
"subnet2": {
"label": "Second subnet",
"defaultValue": {
"addressPrefixSize": "/26"
},
"constraints": {
"minAddressPrefixSize": "/26",
"minAddressCount": 8,
"requireContiguousAddresses": true
}
}
},
"visible": true
}
]
}
Output--
Reference : https://learn.microsoft.com/en-us/azure/azure-resource-manager/managed-applications/publish-service-catalog-app?tabs=azure-powershell
We are seeing different behaviour when we create a workspace in the WebInterface versus when we create the same conversation via the API.
The JSON export for the dialognode is the same:
{ "type": "standard",
"title": "SmallTalk: weerbericht",
"output": {
"text": {
"values": [],
"selection_policy": "sequential" } },
"parent": "smalltalk_container",
"context": { "user_weer": "#weerbericht",
"user_location": "#plaatsnamen" },
"metadata": {
"_customization": {
"mcr": false } },
"next_step": { "behavior": "jump_to", "selector": "condition", "dialog_node": "node_33_1519129633532"
},
"conditions": "#ST_weersbericht",
"description": null,
"dialog_node": "node_9_1517408489377",
"previous_sibling": "node_3_1518680265483" },
But the behaviour is different, which can be explained when we look at the UI
there is a difference
This is the UI for the dialogNode created via the browser
This is the UI for the same dialogNode created via the API
One difference we found is the Multiple Reponse switch:
It should be OFF (image on the right) and as per the JSON (mcr:false).
But even when we switch it on manually, the context variables don't show.
What should I be looking for in the API to fix this ?
The dialog model for multiple condition responses is that the parent node needs to be either standard dialog node or frame. Now when adding a multiple condition response to this node (and hence making an MCR node out of that parent node) you need to add a dialog node with "type":"response_condition" under this node.
This is a way how to create multiple condition responses through the api.
To give you and example to create MCR node:
The JSON of dialog nodes that need to pushed through the API will look like:
{
"type": "standard",
"title": "mcr node",
"output": {
},
"parent": null,
"context": null,
"metadata": {
"_customization": {
"mcr": true
}
},
"next_step": null,
"conditions": "#book_flight",
"digress_in": "does_not_return",
"description": null,
"dialog_node": "node_8_1525086089064",
"digress_out": "allow_all",
"previous_sibling": null
},
{
"type": "response_condition",
"title": null,
"output": {
"text": {
"values": ["I see city entity!"]
}
},
"parent": "node_8_1525086089064",
"context": null,
"metadata": {
},
"next_step": null,
"conditions": "#city",
"description": null,
"dialog_node": "node_9_1525086100114",
"previous_sibling": null
},
{
"type": "response_condition",
"title": null,
"output": {
"text": {
"values": ["I don't see anything."]
}
},
"parent": "node_8_1525086089064",
"context": null,
"metadata": {
},
"next_step": null,
"conditions": "anything_else",
"description": null,
"dialog_node": "node_10_1525086122332",
"previous_sibling": "node_9_1525086100114"
}
I have been successfully using this awesome library and concept called json schema form.
https://www.npmjs.com/package/angular2-json-schema-form
Now using the schema patterns given I am able to generate a form based on a dynamically created schema from database. I want to convert the single form in multiple tabs. I.E I want to group certain kind of fields in one panel.
Is there any kind of support for this functionality? So that I can assign the css class according to the layout.
https://angular2-json-schema-form.firebaseapp.com/?set=ng-jsf&example=ng-jsf-flex-layout&framework=material-design&language=en
You can split group of fields into separate tabs using the fieldsets property.
See the following example from README.md:
{
"properties": {
"firstName": {
"type": "string",
"description": "First name"
},
"lastName": {
"type": "string",
"description": "Last name"
},
"email": {
"type": "string",
"description": "Email"
},
"notificationsFrequency": {
"type": "string",
"description": "Notifications frequency",
"widget": "select",
"oneOf": [
{
"description": "Daily",
"enum": [
"daily"
]
},
{
"description": "Weekly",
"enum": [
"weekly"
]
},
{
"description": "Monthly",
"enum": [
"monthly"
]
}
],
"default": "daily"
}
},
"fieldsets": [
{
"title": "Personal information",
"fields": [
"firstName",
"lastName",
"email"
]
},
{
"title": "Account settings",
"fields": [
"notificationsFrequency"
]
}
]
}
I have taken the Blog App, added a Category ContentType as a field in the BlogPost ContentType and built a query to factor Category into the results.
But I am having trouble with the In-ValueProvider. Following the example here the Visual Query Designer seems to be ignoring the incoming value from my ModuleDataSource.
I have double checked the In-Stream name, my Entity names, case, TestParameters, etc. Are there any known bugs in 2sxc 8.44 and up that would cause this issue? What have I missed?
In this case I am using a RelationshipFilter. Relationship is "Category". Filter is "[In:Config:Category]". I can switch out to a [Querystring:Category] and that works fine and runs all my code.
Thanks for reading.
OK I found a workaround.
It turns out that the In-ValueProvider is working but it's struggling with the Category of my BlogPost I think because Category is an entity.
For background I have a BlogPost ContentType, a Category ContentType, and an Articles Home Header ContentType. Articles Home Header sets both the header info for the articles page and the Category entity.
For some reason the RelationshipFilter is having trouble comparing the Category entities between Articles Home Header and BlogPost. I tried the following for my Filter and neither worked:
[In:Config:Category]
[In:Config:Category:Title]
I wonder if this is a case sensitivity issue, a bug, or if I am just misunderstanding the filter syntax.
To work around I created a temp field called TempCategory in my Articles Home Header and used [In:Config:TempCategory] for the filter.
That worked.
For reference here is a snippet from the Query:
{
"Config": [
{
"Title": "Coaching Articles",
"SubTitle": "",
"Image": "/Portals/0/uploadedimages/AcademicPrograms/Christ_College/crosswise-hero.jpg",
"ImageAlt": "Crosswise stained glass",
"Category": [
{
"Id": 2716,
"Title": "Coaching"
}
],
"Id": 3118,
"Modified": "2016-06-21T10:44:21.9Z",
"_2sxcEditInformation": {
"sortOrder": 0
}
}
],
"Paging": [
{
"Title": "Paging Information",
"PageSize": 10,
"PageNumber": 1,
"ItemCount": 0,
"PageCount": 0,
"Id": 0,
"Modified": "0001-01-01T00:00:00Z",
"_2sxcEditInformation": {
"entityId": 0,
"title": "Paging Information"
}
}
],
,
"Default": [
{
"Title": "Protect Your Players and Your Program: An Athletic Leader's Legal Duties",
"UrlKey": "an-athletic-leaders-legal-duties",
"PublishingGroup": null,
"PublicationMoment": "2016-06-15T00:00:00Z",
"Image": "/Portals/0/uploadedimages/AcademicPrograms/Graduate/Coaching/an_athletic_leaders_legal_duty.jpg",
"ImageSquare": false,
"Teaser": "<p>When the clock started on the new year earlier this month, all but one state joined the growing legal effort to protect and prevent concussions and head injuries among America’s young.</p>",
"Body": "<p><strong>When the clock started on the new year earlier this month,</strong> all but one state joined the growing legal effort to protect and prevent concussions and head injuries among America’s young.</p>\n<p>As sports-related injuries and issues continue to dominate the headlines and influence programs throughout the country, laws like “return-to-play” are becoming a sign of the times when it comes to protecting players and athletic programs alike. The world of athletics is experiencing a significant shift in the perception of the roles and responsibilities of coaches, schools and athletic personnel.</p>",
"DesignedContent": [],
"Tags": [
{
"Id": 2576,
"Title": "coaching"
},
{
"Id": 2575,
"Title": "management"
},
{
"Id": 2574,
"Title": "sports"
},
{
"Id": 3035,
"Title": "legal"
}
],
"Author": [
{
"Id": 3030,
"Title": "Shaleek Blackburn"
}
],
"ImageAlt": "Referee holding a red",
"Thumbnail": "",
"ThumbnailAlt": "",
"RelatedArticles": [
{
"Id": 2564,
"Title": "Athletic Personnel's Duty To Warn"
},
{
"Id": 2565,
"Title": "Get A Better Grip On Bullying"
},
{
"Id": 2717,
"Title": "Good Coaching Develops Exceptional Athletes and People"
}
],
"Category": [
{
"Id": 2716,
"Title": "Coaching"
}
],
"ArticleRelationships": null,
"Id": 2513,
"Modified": "2016-06-15T19:32:17.913Z",
"_2sxcEditInformation": {
"entityId": 2513,
"title": "Protect Your Players and Your Program: An Athletic Leader's Legal Duties"
}
}
]
}
I have the following data structure:
"users": {
$userid: {
"forms": {
"ID_OF_FORM 1": { "name": "Name goes here" },
"ID_OF_FORM 2": { "name": "Name goes here" }
}
}
}
I want to be able to put my "forms" in a folder system to better organize all of them for the user. Right now I call them using /users/auth.id/forms/ID. I was planning on putting objects inside the forms object but I don't think i'll be able to call them with just the form id anymore if I do that.
I can't wrap my head around how I should store these folders so that they can easily be displayed.
I need to display all the folders inside root or the active id of
a folder that a user is currently in.
I also need to be able to call a form using the id of the form
Do you think this would work? Does anyone have any better suggestions on going about doing this?
"users": {
$userid: {
"forms": {
"ID_OF_FORM 1": { "name": "Name goes here", "folder_id": "ID_OF_FOLDER" },
"ID_OF_FORM 2": { "name": "Name goes here", "folder_id": "ID_OF_FOLDER" }
},
"folders": {
"ID_OF_FOLDER 1": { "name": "name of folder" },
"ID_OF_FOLDER 2": { "name": "name of folder" },
"ID_OF_FOLDER 3": {
"name": "name of folder",
"ID_OF_FOLDER 4": { "name": "would this even work" }
}
}
}
}
Looks fine to me, although it is difficult to be certain unless one knows all use-cases (for which StackOverflow is not really the right forum).
I would change the folders a bit into:
"folders": {
"ID_OF_FOLDER 1": { "name": "name of folder" },
"ID_OF_FOLDER 2": { "name": "name of folder" },
"ID_OF_FOLDER 3": { "name": "name of folder" },
"ID_OF_FOLDER 4": { "name": "would this even work", "folder_id": "ID_OF_FOLDER 3" }
}
Otherwise you run the risk of going over the 32 level limit that Firebase imposes on the depth of the tree. The nice thing is that you can directly access any folder by its ID here.
You may consider using a single top-level node for all item types, both forms and folders (and anything else that might come along as you're building the application):
"items": {
"ID_OF_FORM 1": { "type": "form", "name": "Name goes here", "folder_id": "ID_OF_FOLDER" },
"ID_OF_FORM 2": { "type": "form", "name": "Name goes here", "folder_id": "ID_OF_FOLDER" }
"ID_OF_FOLDER 1": { "type": "folder", "name": "name of folder" },
"ID_OF_FOLDER 2": { "type": "folder", "name": "name of folder" },
"ID_OF_FOLDER 3": { "type": "folder", "name": "name of folder" },
"ID_OF_FOLDER 4": { "type": "folder", "name": "would this even work", "folder_id": "ID_OF_FOLDER 3" }
}
But I don't think this is too beneficial for your use-case at the moment. Given what you've said, the split between folders and forms seem pretty good.