I have a business requirement (which is not going to change) to display about 10,000 items on a page (I don't like it). The items are related via a parent child relationship much like folders, sub folders and files on a disk drive.
I want to build the page in such a way that it is driven by a javascript data structure (internal application, javascript will always be enabled).
Is it generally better to have a flat data structure where each record contains a link to its parent, or is it generally better to have a structured data structure where each "folder" contains references to "sub folders" and "files"?
Ie:
var items = { //flat array
{id:1, parentId:0},
{id:2, parentId:1},
{id:3, parentId:1},
{id:4, parentId:2},
{id:5, parentId:2}
};
var items = { //structured
{ id: 1, children: {
{ id: 2, children: {
{ id: 4 },
{ id: 5 },
} },
{ id: 3 },
} }
};
Off the bat the flat format seems easier on the eyes, but the server will be generating that list so honestly that isn't such a big deal. How would performance compare? With flat, there would need to be much more DOM lookups, ie find element with id=1 and insert DOM element for id=2. The structured format has all the relationships defined so as the javascript code is navigating the structure it can create all the DOM elements needed without additional lookups. So which method would generally be more performant?
Structured. It's more scalable and will be easier to manipulate nodes in the DOM with JQuery.
Related
I'm to get an answer on whether or not the way my database is setup will cause too many recursive reads and therefore exponentially increase the number of read operations.
I currently have a collection of users, inside of each user doc, I have 3 other catalogs, goods, bundles and parts. Each user has a list of parts and a list of bundles, for example.
Each doc in the bundles catalog has an array of maps with a reference to a doc in the parts catalog in each map.
When I query the bundles, I want to also get the details of each part in the bundle. Does this require that I run another onSnapshot?
Here's an example:
database:
users (catalog)
userID
parts
partID1
partID2
partID3
bundles
bundleID1
title: "string",
parts: [
part:"/users/userID/parts/partID1,
qty: 1
]
parts: [
part:"/users/userID/parts/partID2,
qty: 1
]
parts: [
part:"/users/userID/parts/partID3,
qty: 1
]
getting the bundles
initBundle(bid) {
const path = this.database.collection('users').doc('userID').collection('bundles').doc(bid);
path.ref.onSnapshot(bundle => {
const partsArr = [];
bundle.data().parts.forEach(part => {
part.part.onSnapshot(partRef => {
const partObj = {
data: partRef.data(),
qty: part.qty
};
partsArr.push(partObj);
});
});
const bundleObj = {
title: bundle.data().title,
parts: partsArr
};
this.bundle.next(bundleObj);
});
return this.bundle;
}
I'm using Ionic/Angular for this, so when I return the item, it needs to be an array of objects. I'm sort of recreating the object to include each part on this init. As you can see, for each part in the bundles return, I am doing another onSnapshot. This seems incorrect to me.
Something that is dawning on me is that I probably should be making a single call to the user, which in turn returns everything? But how do I get the sub catalogs at that point? I'm not sure how to proceed without racking up a bill!
If you do a nested part.part.onSnapshot(partRef => { listener, be sure to manage those listeners. I know of three common approaches:
Once your outer onSnapshot listener disappears, the nested ones should probably also be stopped (as their data likely isn't needed anymore). This is a fairly simple approach, since you just need one list of listeners for the entire bundle
Alternatively you can manage each "part" listener based on the status of that part in the outer listener, removing the listener for "part1" when that disappears from the bundle. This can be made into a highly efficient solution, but does require (quite some) additional code.
Many developers use get()s for the nested document reads, as that means there is nothing to manage.
I have a Rest endpoint, that sends and receives objects of the form
[
{id: 1, Name: "Type"},
{id: 2, Name: "Type:Subtype"},
...
]
I want to display this in an editable tree, using Sencha Extjs 6. I am confused as to where and when to transform the data, and how to keep changes synchronized without side effects. My current (not nice) method is to reload the data and then reset the tree's store using the converted values, but that collapses all of the expanded nodes
I can get and save entries using a model and a store
I can convert the data into a form suitable for use in a treepanel
I do not know the "right" way to do so, and to have changes in either store reflected in the other.
For clarity, the converted tree store has a data stucture:
[
{
text: "Type",
children: [
{
text: "Subtype",
isLeaf: true
}
]
}
]
Came up with the answer: a save button.
Bound the Load event of the Rest Store to the controller, and in that method copied the values into the TreeStore.
Edits are made to the TreeStore - kept purely client side
Save button copies new data back into Rest Store and calls sync(). Easy to follow. Code is kept mostly declarative. And I can provide default values in the VM's data field. Easy to do - shame it's not made clear in the documentation somewhere
In my Ember app, I have a complex model that looks like below (kind of contains 2-dimensional array)
[
[
{
id: 'Section1_123',
label: 'abc'
},
{
id: 'Section1_456',
label: 'xyz'
}
]
],
[
[
{
id: 'Section2_123',
label: 'abc'
},
{
id: 'Section2_456',
label: 'xyz'
}
]
]
There are a lot of other attributes, but this is the overall structure.
Now my question is can I drill-down & find a specific object. It has unique ids (as shown in the example above)
So I need something like model.findBy(Id)
I then need to change/set some values for that object. Say I want to change the obj.label from 'abc' to 'abc_NEW'
Just to add, The main model is actually a simple JS array...but the inside objects (e.g. those with id: 'Section1_123', etc) are actually Ember objects
Most common approach to work with data in Ember is EmberData. And because the main credo of Ember is "convention over configuration" then a common way in Ember is the best way, in my opinion.
There are many ways how to deal with your data format. I would recommend to create model for each item:
import DS from 'ember-data';
export default DS.Model.extend({
label: DS.attr()
// other properties
});
Then you can make a custom serializer according this article. The goal is to convert your arrays to list of EmberData models.
After this you can use standard EmberData functions to work with data (including access by object id, of course).
The server responds with something on the form:
{'dates':
{'2013.05-17':
{'activities':
{'activity 1':
{time: 0, 'synced': false},
'activity 2':
{time: 5, 'synced': false},
'activity 3':...
},...
},
'2013.05-18':
{ ...}, ...},
'id': id}
I currently put everything in a single Backbone model, which doesn't seem like the proper way to do it. The examples I've read around the web all use very simple models where there's no nestled structures and the mapping is pretty simple e.g. {x: 1, y: 2} being mapped to a coordinate model and so on.
What's the "correct" way to map the above JSON structure to Backbones models/collections?
As Protostome mentions, Backbone Relational is good for this kind of thing.
However looking at the JSON data that you have used as an example, from my viewpoint you have only one model and collection as follows:
Activity Model
Activities Collection
Even though you have a nested set of data you could look at it in a different way which gives you a simple backbone model, for example:
var activity = {
id: "Activity 1"
time: 0,
synced: false,
date: "2013.05-17"
batchId: id // this corresponds to the id property in your example
}
This represent all of the data contained in your complex nested hierarchy more simply, and more importantly suited to the way Backbone works.
If you cannot alter what the server provides you, you could use the Underscore library functions (from memory _.map()) to map the JSON you receive into simple JSON objects ready for use with Backbone.
I am hoping that maybe you can simplify your design by thinking outside the the context of sticking with a hierarchy?
In the context of a web app, I have a server which sends or receives JSON strings based on the input from the client. On client consumption, these JSON strings are immediately converted into JavaScript objects where they will live out their lives as objects. These objects are not arrays; they represent complex, arbitrary data models, each property of which can have an arbitrary number of unique subproperties or objects.
var myView = {
name: 'root'
id: 'root_0'
children: {
child_1: {
arbitraryid: 'root_0_child_1',
type: 'Department',
name: 'Produce',
quadrant: 1,
children: {
child_1: {
arbitraryid: 'root_0_child_1_child_1',
type: 'Aisle',
number: 3,
length: 12,
children: { }
}
}
},
child_2: {
arbitraryid: 'root_0_child_2',
name: 'West',
type: 'Region',
children: {
child_1: {
arbitraryid: 'root_0_child_2_child_1',
name: 'Wegmans',
type: 'Store',
children: {
child_1: {
arbitraryid: 'root_0_child_2_child_1_child_1',
type: 'Department',
children: { }
}
}
}
}
}
}
};
When I build the JSON string server side, I guarantee that all objects will have 'children' and 'arbitraryid' properties; but everything else is dynamically generated and the properties and values are completely arbitrary.
If this were XML, I could use jQuery to var someChild = myView.find('#root_0_child_1_child_1'). This would get me a jQuery object with the results of the find AND not only a reference to myView but a position from which to move omnidirectionally through the object: var someChild = myView.find('#root_0_child_1_child_1').parent().
Does a utility exist to solve this problem for native, JavaScript objects or is there a preferable way/methodology to do this? I'd like to avoid writing a bunch of this type of code to simply get at my property and then potentially loop again to update the parent object.
while (obj.hasOwnProperty('children')) {
for (var child in obj) {
//..etc, etc
}
}
Most of the SO questions I see on this subject deal with searching arrays, frequently with predictable data table style construction.
Mapping is possible, but these objects quickly become deep and that option seems little better than dumb looping.
Ideas?
Edit: rolling my own utility class.
I'm still exploring other libraries/utilities, but I wrote a generic helper class to do searches:
ObjectHelper
While useful, I think it illustrates some of the difficulty with getting at other jQuery-like functionality. Not only would I like to search, but I'd like to be able to crawl up/down the object property structure similarly to the way you can chain .parent().children().find() operators together. Doable, but complicated.
I found a few JSON Query Languages:
JSONPath
JAQL
LINQ to Javascript
JSINQ
jLinq
SQLike (despite the name, it's used for querying JSON)
TrimQuery (uses a SQL-like language to query JSON objects)
This page sums them up and goes through their pros and cons.
There is a DOJO module for querying JSON as well:
JSONQuery
I'm not sure how stable/standard these are though.
I solved this by rolling my own classes. ShadesJS is pretty basic right now, but it has some methods for crawling JavaScript objects and working with Web Storage. On the to-do is implement parent/child methods to get some JQuery-esque flexibility. It's not hard to do, but it's tricky to get it right and performant.