Neo4j : best alternative to storing nested properties? - json

I have an existing live neo4j db with relationships like this...
User-[:Owner]->Item
User contains the usual properties; name, email etc.
Owner relationship has created_on property
Item has a bunch of properties about the item; title, description etc.
I want to add in a geo-location property for the Item. This will be a latitude and longitude of where the user created the item.
A JSON api is serving up this data to our clients. The API will merge some of the data, so an Item object in the api will have a nested User object as a property of it...
"item": {
"title":"my item",
"user":{
"name":"smith"
}
}
And I was initially thinking the location would follow suit...
"item": {
"title":"my item",
"user":{
"name":"smith"
},
"geo_position":{
"latitude":"10.123456789",
"longitude":"10.123456789"
}
}
As we cant nest data in Neo, was wondering how to store this data...
JSON serialise the latitude and longitude data under a geo_position property of the Item ?
As properties of the relationship Owner.latitude?
As a new Node ? Location `User-[:owns]->Mite<-[:created_at]-Location?
As individual properties of the Item so not nested, item.latitude ?
1 - I assume we cant query.
2 - doesn't feel like the right place.
3 - its extremely unlikely 2 Items will have the same location as lat long is very precise, so almost No Items will share this node, so is it really a node?
So is 4 really the way to do it, and just not nest them ?
m

You own analysis is basically correct. I would go with number 4.
Here is more about why number 2 is not a good idea. Logically: the location of an item belongs in that item's node, not in a particular relationship to it. Practically: if the object changed ownership you should not have to copy its location to a new relationship, and querying for an item's location should be as quick and simple as just getting its node.

Related

The best way to represent big organizational structure in browser in the most efficient way

colleagues! We are developing a web application which has functionality to represent the organizational structure of current organization(a bank, for example). Organizational structure is represented as a parent-child relationships where each node has only one parent and each parent may have zero or more children. When the amount of entities(orgUnits) was comparable small, about 500 entities, our old method worked well. Generally, we used recursion to get all parent-child entities and passed it as a JSON document to browser where frontend part parsed this document and rendered it for user. Problems started when we uploaded the organizational structure of another organization(another bank) and had 6000 active orgUnits. Obviously fetching all orgUnits was not an option. We started to use request param depth to control recursion level but it didn't solve the problem of fetching child entities because each parent can have one or more children. For example, we had a parent orgUnit that had 100 children and any of this child could have one or more children. This method also loaded all orgUnits on this level even if it wasn't necessary. Right now i'm looking for solution that will keep number of orgUnits per HTTP request relatively small and browser won't freeze while rendering it. My idea is simple:
Paginate results somehow;
Only return additional child orgUnits when user wants it;
Our OrgUnitDTO looks like this:
{
"id": "a4f51de5-36f3-258c-232d-3d617c07fefc",
"extId": null,
"type": "OrgUnit",
"orgId": "99beadc8-831a-f6ab-fee9-11143d43ccd1",
"parentId": "99beadc8-831a-f6ab-fee9-11143d43ccd1",
"code": "second-level-test-department",
"name": "name",
"note": "note",
"manager": null,
"children": [], // children property has objects of the same type
"createdBy": "userName",
"updatedBy": "userName",
"createdAt": "2020-09-04T06:23:53.793Z",
"updatedAt": "2020-09-04T06:23:53.795Z",
"sortOrder": 0,
"isManager": false
}
That's how it looks in GUI:
screenshot
I'm looking for your suggestions for backend and frontend as well!
In case it matters we use Spring-Boot and Hibernate.
Here is not a matter of framework used or technology.
Your question is more about the solution.
Rule of thumb: A human can interact only with few data at a time, so don't fetch or display a lot of data, is useless and slow.
I've dealt with a similar problem in the past and solved this way, but there may be better solutions of course:
I've created a backend function that a client can call to fill the page the first time is loaded so that you can get the first N levels of depth with an integer parameter (ie. 2 or 3) starting from a node of the tree (null if you want to start from the top).
I've added a search function (both on FE and BE) to let the user jump immediately to a position he already knows (ie. an employee name): the function returns only the JSON of the nodes that are composing the path to the founded node. Other nodes can be expanded with a [+] button or something like that, just to be hyperfast and concise in outputting data. Usually, if you search for a person in an org chart, you want to know immediately who are his bosses and nothing else.
Children for each node were not so many in my case, so I've not optimized here, but in your case, you can implement lazy loading of data with pagination if you have more than X children at the same level. You can use a \/ icon to load more nodes when the user clicks or you can do it automagically when the user scrolls down the page. It is up to you. It is up to you decide also the number of nodes to load after paging. You can make this responsive, you load more nodes if the screen has space to display them.
To open each subsequent node call the function you used at the first-page loading only when the user clicks on the [+] passing the current node id and 1 as parameters to specify you want only one level more.
To implement the FE part I've used jstree and jstreegrid.
General hint: choose the FE part library first, THEN create backend functions, it will be easier and you'll make fewer refactorings.

SearchBar deep search into JSON

I'm implementing a searchbar in IONIC 2 that search a JSON in one view so it can send its details to another view.
I have this JSON:
{
"Alphaville I": { //FIRST KEY
"ida": [{ //SECOND KEYS
"hora": "05:40",
"local": "AV. FERNÃO DIAS PAES LEME (Pref. Várzea Paulista)"
},... ],
"volta": [{ //SECOND KEYS
"hora": "05:40",
"local": "AV. FERNÃO DIAS PAES LEME (Pref. Várzea Paulista)"
},... ]
}, ... //MULTIPLE ITENS
}
So, in one view i create a list with the first keys (like Alphaville I), but i need to search the local inside of it.
But the Angular 2 *ngFor requires an array, so i iterate through my object and push it to an array, doing this it excludes my first key, so what i'm doing now (without searching, of course) is saving the keys in one array, geting the index and passing the jsonResultExample[index] to another page.
i'm using the basic searchbar example like the one in Seachbar Component Docs.
So what i need is: Search by the local key and return the first key (Alphaville I) of the nodes the contain the input text, the same local can appear in other first keys.
How can i do this? I can't post a better code because i haven't tried anything.
Is there a better way to structure my JSON for this? (i'm using firebase btw);
Any help or ideas is welcome, thanks.
EDIT
So i saved the first key value along with ida and volta so i can simply iterate through it, get the key value and everything without many problems, but since i need to filter by local it appears inside idaand volta as another array (cause i have many of these values), so it's looking like this now:
So now how can i access the local? Is it better to create another object only with all local and a key for every linha so i can return the values?
Remembering this is the searchbar code for Ionic 2 and my JSON has over 4k lines:
getItems(ev: any) {
// Reset items back to all of the items
this.initializeItems();
// set val to the value of the searchbar
let val = ev.target.value;
// if the value is an empty string don't filter the items
if (val && val.trim() != '') {
this.items = this.items.filter((item) => {
return (item.toLowerCase().indexOf(val.toLowerCase()) > -1);
})
}
}
Thanks in advance :)
It comes to personal experience on how to design data structure. Therefore I can't say the follow method is the best way.
First, in the case that we have complicated data structure, I don't prefer using map (a.k.a. object as data structure) in javascript. The main reason is pretty related to what you are facing, object by design cannot be iterated. Yes you can use Object.keys() or Object.values() but they are so ugly and hard to fit on every cases.
It is a nice move to put your first key as a property. That comes to the second problem. There seems to be an assumption in your structure that, one linha is mapped only to one local or one local is only related to one linha. If so, I suggest building another separated map only for the linha and local relationship.
Another approach is to normalize your data structure in to multiple separated javascript objects like what you do on database. By doing so, you can maximize the data flexibility that you can query whatever you want by Array.prototype.filter(), Array.prototype.map() or even directly access by its index. However, this approach may increase the lines of code as you need to manage multiple maps.

Return State ID from Containing County Event

I have a topojson map that has both county and state data in json format. There are no actual names for the states, but the states do each have a unique id. I would like to find a way to return the id of a state if the user clicks on one of its containing counties.
The trouble is I cannot seem to be able to access the state ids in the json when I set up my click event listener. I have sliced and diced the json data every which way, but I keep going in circles. Is it possible to have asymmetric information within the json file? I feel like the state ids are in a black box when working with the containing counties.
Let me know if anything comes to mind. I have a fully functional minimalist example here, where I am trying to return a console log of the state id based on user click.
Note: I would prefer to avoid point in polygon solutions for complexity reasons.
Seems your json file ships with FIPS county code. That means that first two digits of county code are in fact the state code. So Math.floor(county.id / 1000) is what you‘re looking for in the end.

Formatting a json returned by a RESTful API

If you were to call a restful api and were expecting to get a number (not one item) of items in json format. What would be the most correct format for an api to give this data to you:
a) [{"a":1, "b":2}, {"a":3,"b":4}] or
b) {"element1":{"a":1, "b":2}, "element2":{"a":3, "b":4}}
Or maybe there is a third way? Which one would be correct from the perspective of users working with this api?
If you were to call a restful api and were expecting to get a number (not one item) of items
Considering options A [{"a":1, "b":2}, {"a":3,"b":4}]
and B {"element1":{"a":1, "b":2}, "element2":{"a":3, "b":4}}
A is a list of items (note the [ ]). B is a single item (note the { }).
B just so happens to be an item that has multiple sub items, but it is still 1 single item.
Therefore your answer would be to go with A, as A is a list of items.
The 2 solutions are possible of course. But solution 1 is more light (not need to create a "element1", "elementN" for each item) and it's provide a more generic structure (for REST API especially).
And, also it's depends how you want manipulating the data. With array (solution 1), it's maybe more easy.

RESTful API for related objects

I am fairly new to REST and I have been struggling to map out RESTful requests for objects that are related by foreign keys in a mySQL database.
I have following objects and their relationships are in linear order:
Quiz_course [1]
Quiz_meta_block [2]
Quiz_block [3]
Quiz_question [4]
So far I have come up with the following GET requests:
// Retrieve all quiz_course(s)
api/quiz_course/
// Retrieve quiz_course by id
api/quiz_course/{id}
// Retrieve all quiz_meta_blocks related to a quiz_course id
api/quiz_course/{id}/quiz_meta_block
// Retrieve a quiz_meta_block that is related to a quiz_course_id
api/quiz_course/{id}/quiz_meta_block/{id}
But then I hit a wall when trying to get quiz_questions :
// Retrieve all quiz_questions that is related to a quiz_course_id
api/quiz_course/{id}/quiz_meta_block/quiz_block/quiz_question/
Is my representation accurate ?
I don't know what a block or meta block is in the context of a course, but I would go with something like the below. No need to prefix everything with quiz_*
../courses
../courses/n
../courses/n/meta-blocks
../courses/n/meta-blocks/n
../courses/n/meta-blocks/n/blocks
../courses/n/meta-blocks/n/blocks/n
../courses/n/meta-blocks/n/blocks/n/questions
../courses/n/meta-blocks/n/blocks/n/questions/n
You could also give direct access to, say, all questions in a course like this:
../courses/n/questions