How to develop form interfaces for schema-less databases? - database

If you are using an SQL database, it's very straightforward to develop a user interface for CRUD operations. Since the schema is defined, it's obvious how many inputs you need in a form, etc.
But when using a schema-less NoSQL approach for storage, how do you build interfaces since you don't know exactly what to expect from the types of data being stored? For example if you had a database of cars:
var cars = [
{ model: "BMW", color: "Red", manufactured: 2016 },
{ model: "Mercedes", type: "Coupe", color: "Black", manufactured: “1-1-2017” }
];
If you needed to create a user interface so you could access and edit this data, you have no clue how many inputs you need since there is no schema. How do UI developers solve this problem?
Do you have a bunch of if statements to test if every possible attribute exists in the record before showing the proper inputs?
// psuedo code
if ($car.hasKey("model") ) {
// Show the "Model" input form element
}
if ($car.hasKey("type") ) {
// Show the "Type" input form element
}
if ($car.hasKey("color") ) {
// Show the "Color" input form element
}
if ($car.hasKey("manufactured") ) {
// Show the "Manufactured" input form element
}

If you needed to create a user interface so you could access and edit this data, you have no clue how many inputs you need since there is no schema. How do UI developers solve this problem?
You solve this by reasoning from feature requirements. Emphatically, you do not try to generate forms (automatically or otherwise) from schemas: that is a recipe for poor UX even if you do have a comprehensive, canonical and unequivocal schema to hand.
Instead: you know what your 'use cases' are (you ask users) and then you build exactly those.
So the question becomes:
What do you do when your data item/instance does not contain a particular object/field/key which you did expect?
What do you do when your instance contains fields which you do not know what to do with?
The answer for #1 is pretty straightforward, and basically just the same as dealing with schema changes: assume/present sane defaults or handle null values gracefully. That is: permit your users to add such fields later where they make sense and do not choke on objects that lack them.
The answer for #2 is more complicated and it is going to depend heavily on the application and its environment (for example: is it the sole consumer of the data, or are there other consumers to consider as well). One option could be normalisation: you prune such extraneous fields on saving, so objects become normalised over time as they are updated by the users. An alternative could be preservation: you keep any fields you do not know as-is, and you take pains to preserve them through every layer of your application.

Related

How can I allow users to add options to a product listing from a coding perspective?

Creating an eCommerce type react application and part of it is merchants can create product listings(item title, item description, item price, etc). How do I allow them to add options to the listing like Size, Color, etc. It seems more confusing than just having input fields that can change a state variable.
An example of what a completed array should look like after a user enters options:
const options = [
{
optionName: 'Size',
values: ['small', 'medium', 'large']
},
{
optionName: 'Color',
values: ['blue', 'black', 'white', 'tan'],
}
]
Above is how it should be constructed to be sent to server.
Let me know if any more clarification is needed.
What you're describing is dynamic form construction, and is always much more complicated than a static form. This is not an easy feature to implement.
What you've sketched out there as dummy API request data is essentially the solution -- you just need to provide UI that enables that solution. Presumably you have an object that holds all your form data, so you can add a field like userDefinedOptions that gets initialized with an empty array.
Then, you'll need UI elements to allow adding a new user-defined option, which will probably include the display name of the option, as well as the list of choices for that option. This UI would then call an event handler that inserts the inputted values into your list of user-defined options.
Dynamic forms can get very messy very fast, so I'd recommend looking into a form library to handle some of the overhead. You'll also need to validate the dynamic user data before sending it off to the API.
Hope that helps!

How to create the following data structure in a NoSQL environment

Intro
I have a FireStore database similar to a social media db, with 3 collections Users, Events, and EventUpdates. My goal is to create a feed with eventUpdates created by me and my friends. So i have to expand my database with friendship connections. But i struggle with 3 problems, and hopefully somebody here can push me in the right direction to solve these.
Problem/Question 1:
I added username and user image to the EventUpdate model so it's easier to query. I've heard denormalise is the way to go in a NoSQL database. But if a user updates his user image, i've to update all eventUpdates created by that user. Sounds like something you don't wanne do. But is there a better way to do this?
Problem/Question 2:
How can i create a data structure that is optimised for performing the following query: get eventUpdates from me and my friends ordered by date.
Problem/Question 3:
How to store likes? I can keep a counter in a eventUpdate. But this becomes a problem when i denormalise eventUpdates (see current solution underneath EDIT)..
Data structure example .
{
"users": {
"1": { "name": "Jack", "imageUrl": "http://lorempixel.nl" }
},
"events": {
"A": {
"name": "BeerFestival",
"date": "2018/09/05",
"creatorId": "1"
}
},
"eventUpdates": {
"1": {
"timestamp": "13243543",
"creatorId: "1",
"creatorName": "Jack",
"creatorImageUrl": "http://lorempixel.nl",
"eventId": "A",
"message": "Lorem ipsum"
}
}
}
EDIT
OK, after some trial and error i ended up with the following structure. This structure seems work, but my problem with this solution is that i need to make a lot of write calls to update a single eventUpdate because of all the copies in each feed (1000 followers means 1000 copies). And it looks like i need to do that a lot.
I would like for example to add a like button to each event update. This trigger an update on all EventUpdate copies. For me it looks like firebase is not suited for my project and i'm thinking of replacing it with a SQL DB, or can anyone here change my mind with a better solution?
{
"users": {
"user1": { "name": "Jack",
"imageUrl": "http://lorempixel.nl",
"followers": ["user1"]
}
},
"feeds": {
"user1": {
"eventUpdates": {
"1": {
"timestamp": "13243543",
"creatorId: "1",
"eventId": "A",
"message": "Lorem ipsum"
}
},
"following": {
"user1": {
"name": "Jack",
"imageUrl": "http://lorempixel.nl",
"followers": ["user1"]
}
}
},
"events": {
"A": {
"name": "BeerFestival",
"date": "2018/09/05",
"creatorId": "1"
}
}
}
I added username and user image to the EventUpdate model so it's easier to query. I've heard denormalise is the way to go in a NoSQL database.
That's right, denormalization and is a common practice when it comes to Firebase. If you are new to NoQSL databases, I recommend you see this video, Denormalization is normal with the Firebase Database for a better understanding. It is for Firebase realtime database but same rules apply to Cloud Firestore.
But if a user updates his user image, i've to update all eventUpdates created by that user. Sounds like something you don't wanne do. But is there a better way to do this?
Yes, that's also correct. You need to update all the places where that image exists. Because you have chosen google-cloud-firestore as a tag, I recommend you see my answer from this post because in case of many write operations, Firestore might be a little costly. Please also see Firestore pricing plans.
Regarding Firestore, instead of holding an entire object you can only hold a reference to a picture. In this case, there is nothing that you need to update. It's always a trade between these two techniques and unfortunately there is no way between. You either hold objects or only references to objects. For that, please see my answer from this post.
How can i create a data structure that is optimised for performing the following query: get eventUpdates from me and my friends ordered by date.
As I see, your schema is more a Firebase realtime database schema more than a Cloud Firestore. And to answer to your question, yes you can create. So talking about Firestore, you can create a collection named eventUpdates that can hold eventUpdate objects and to query it according to a timestamp, a query like this is needed:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference eventUpdatesRef = rootRef.collection("eventUpdates");
Query query = eventUpdatesRef.orderBy("timestamp", Query.Direction.ASCENDING);
But please note that the timestamp field should be of type Date and not long. Please also take a look at my answer from this post, to see how you can add a date property in a Cloud Firestore database.
How to store likes? I can keep a counter in a eventUpdate. But this becomes a problem when i denormalise eventUpdates (see current solution underneath EDIT)
You can simply add likes but I recommend you see the last part of my answer from this post. So you might consider adding that count in a Firebase realtime database rather than in Cloud Firestore. Both databases work very well together.
This structure seems work, but my problem with this solution is that i need to make a lot of write calls to update a single eventUpdate because of all the copies in each feed (1000 followers means 1000 copies). And it looks like i need to do that a lot.
You might also take a look at my answer from this post.
For me it looks like firebase is not suited for my project and i'm thinking of replacing it with a SQL DB, or can anyone here change my mind with a better solution?
I don't think this way. There are many apps out there that have the exact mechanism as yours and are working very well.
If you want your feed items to be in sync with the real users data (new profile image when the user changes it for example) you can simply store the user ID in the eventUpdate document. This way you don't have to keep them in sync manually, and every time you have to display the item in the feed you could simply fetch user data, and easily query many eventUpdates on userId and created_at fields ( assuming you have them ).
To implement likes in your feed the solution depends on a bunch of things like traffic volume.
The simplest way is to update a likes field with a transaction, but Firestore has a maximum updates frequency on a single document of 1 second. Plus, a transaction can easily fail if more than 5 transactions are trying to update the same document.
To implement a more solid likes system take a look at this page from the official Firebase docs.
Firestore has a different approach to the NoSQL world. Once you know the data you will use (as You already do) there are some very important points about what architecture the data will have. And It depends a lot about how the data grows, what kind of queries you will need and how often you will use them. Some cases You can create a root collection that aggregates data and queries might be easier.
There is a great video from Firebase Channel that might help. Check it out!
How to Structure Your Data | Get to Know Cloud Firestore #5
https://www.youtube.com/watch?v=haMOUb3KVSo
[UPDATED] December 26th
Others videos that might help to model and query your data is these videos:
How to Connect Firebase Users to their Data - 3 Methods
https://www.youtube.com/watch?v=jm66TSlVtcc
How to NOT get a 30K Firebase Bill
https://www.youtube.com/watch?v=Lb-Pnytoi-8
Model Relational Data in Firestore NoSQL
https://www.youtube.com/watch?v=jm66TSlVtcc

CakePHP 3 Entity Confusion

Here is the issue I am facing all the time since I started to learn CakePHP 3
What is this concept of entity a real world example would help alot.
public function add()
{
// why do we have to create new entity / what is the role of entity here.
$comment = $this->Comments->newEntity();
if ($this->request->is('post','put')) {
// why do we have to use this line after posting / what is the role of this line.
$comment = $this->Comments->patchEntity($comment,$this->request->data);
if ($this->Comments->save($comment)) {
$this->Flash->success('comment submitted successfully.');
} else {
$this->Flash->error('Sorry, comment could not be updated.');
}
}
return $this->redirect($this->referer());
}
Let me open the book for you:
While Table Objects represent and provide access to a collection of
objects, entities represent individual rows or domain objects in your
application. Entities contain persistent properties and methods to
manipulate and access the data they contain.
-
why do we have to create new entity / what is the role of entity here.
Almost everything, if not all, in Cake3 works with entities, what an entity is is explained above. You need to create a new entity so that the FormHelper can work with it, AFAIR it can still work with an array if configured to do so as well but the entity should be used.
The reason entities exist is to abstract the data. Some people think entities are the representation of a DB row - that's wrong. As the book says, they can be a row but don't have to represent a row because the 3.0 ORM can work with other resources as well. In theory you can have a CSV data source that returns an entity per line.
I suggest you to read the entity code in the CakePHP core to get a deeper understanding of what else entities provide, just saying they're "just" a set of properties is to short thought.
why do we have to use this line after posting / what is the role of this line.
The post data is merged into the previously created entity, that's it. Use the API if you have basic questions like that. See the API entry for patchEntity().
In simple word, Entity is a set of one record of table and their relational table, on that you can perform operation without touch of database and encapsulate property of entity (fields of table) as you want.
Advantages of Entity.
Modifying result sets outside of the database (for formatting or otherwise)
Needing to represent both the table and row in the same class.
Data validation was a fucking nightmare.
Inconsistent API in terms of both how we handled things internally as well as what (and how) we returned stuff.
Other random stuff as you want.
You can do run-time modification of result sets. Just add a method to your entity to return results in the way you want. This also means you can use composition for managing entities (yaya traits)
Validation is beautiful. We can validate data before it gets into an object and then validate the object state in a separate step.
It is easier for developers to understand what they are dealing with. You either have an object or an array of objects. An object can be linked to data which can also include other objects, but you no longer have to guess at what the array key will be, nor whether its nested funkily.
We can iterate on the interface for tables and entities separately. We couldn't easily change internals for the old Model class because of the implications on both, whereas now we can (in theory) change one without mucking about in the other.
It looks prettier simple.
Try this:
if ($this->request->is('post','put')) {
$data = $this->request->getData();
$comment = $this->Comments->newEntity();
$comment = $this->Comments->patchEntity($comment, $data);
$status = $this->Comments->save($comment);
if ($status) {
$this->Flash->success('comment submitted successfully.');
} else {
$this->Flash->error('Sorry, comment could not be updated.');
}
}
return $this->redirect($this->referer());
}
My advice is never use Post and Put in the same function. Just for good pratice. Put works fine when you make a update using id like a parameter.

Get all documents in a CouchDB database *except* the design documents

In couchDB I have a database with some documents. When I create a view, the view is created inside of this database, together with the documents. Then when I take all the elements of the database, couchDB returns me all the elements including the views. Is there any way to get everything apart from the views?
You may use
/<mydb>/_all_docs?descending=true&endkey="_design0"
The '0' in _design0 makes sure that the output is stopped before the first design document. The optional parameter inclusive_end=false may work as well but did not for me in a short test.
See http://docs.couchdb.org/en/latest/api/database/bulk-api.html for further details.
But I'd also prefer a simple view for that task.
Using this should work:
/<mydb>/_all_docs?endkey="_design"
If you use only the auto-generated IDs, then you probably can also use:
/<mydb>/_all_docs?endkey="_"
but that may cause issues if you use custom IDs since the "_" character falls between uppercase and lowercase letters.
One way to do this is to 'categorize' the documents when you insert them into the CouchDB. A common technique to do this is adding a 'type' property to all the documents you created.
e.g.
{
firstName: 'John',
lastName: 'Doe',
type: 'user'
}
Then you can create a view that returns only documents with that property.
function(doc) {
if (doc.type) {
emit(doc._id, doc);
}
}

Extjs 4 Ext.data.Model: How to model nested objects

I'm new to Extjs 4 and I'm trying to understand how to create a model for data that has nested objects.
Example Data:
{
data1:{
field1:1,
field2:2,
**objField1**:{
objField1:1,
objField2:2,
**anotherObj**:{
field1:1,
field2:2,
arrayofObjs:[
{
//...
},
//...
]
}
},
objField2:{
//... Some more fields or objects
},
data2:{
//...
}
}
I'm trying to understand how I would model this data. The fields are easy
Ext.define('MyModel', {
extend: 'Ext.data.Model',
fields: [
{name: 'field1', type: 'int'},
{name: 'field2', type: 'int'}
], //...
But how do you model the objects? I was thinking I could create a model for the sub-objects and setup associations, but after reading the documentation, they seem to need to have IDs. So if you look at the belongsTo page, "The owner model is expected to have a foreign key which references the primary key of the associated model".
I'm not looking to model data that has foreignkey relationships, just objects with sub-objects. So the server might return one JSON object with multiple sub-objects, and one of those objects I might want to tie to a grid, another object's data to a selectbox, etc.
Thanks!
I think you have several problems here.
First, Models in Ext JS are mostly used to represent relational data, i.e. rows in SQL database. You can twist them to do whatever you want, but that doesn't mean it would be easy and there's always the question of "what for".
Second, Ext.data.Model is not suited at all for representing tree-like structures; you can use Ext.data.NodeInterface for that. NodeInterface is kinda class override for Model, a mixin in part, and generally is quite kludgy and rigid thing. The bright side is that it works, and the down side is that there's no other class that does the same stuff.
Next, nested data objects do not necessarily mean that they're actually related to each other. You said you want to pluck objects from one global JSON response; this can be done easily by configuring multiple Stores with different Readers and feeding them the same JSON object.
OTOH, the data structure looks a bit convoluted. Is that an attempt at preliminary optimization on the server side? I.e., put all stuff we might need into one huge JSON to save on server hits? If so, take a look at Ext.Direct remoting; it can save you from lots of headache down the road.

Resources