multiple hierarchy in coredata - ios

I do have a problem where I am having a hard time figuring out how to lay out the relationship in coredata. I tried to visualize the problem below.
Basically in my application users have STATEMENTS that are made of TERMS.
One or more TERMS make STATEMENTS[1].
Users can also tap on a term[2] and
create another statement that's connected to this term[3].
Once they solve this sub statement[4]
they can go back to the main statement [5] and highlight another term and so on.
They should be able to go deeper than one level if need be. Say, select another term in sub statement and create another statement etc.
I am not sure how to create such a schema in coredata.
I already have my TERM and STATEMENT entities, and I initially separated STATEMENT AND SUBSTATEMENT as two different entities but I am not entirely sure if this is a approach anymore.
I think a more efficient approach would be to store each statement in just one entity and have a relationship with TERM but I Am not sure how to figure out the levels.
I would appreciate any directions.

Related

Node vs Relationship

So I've just worked through the tutorial and I'm unclear about a few things. The main one, however, is how do you decide when something is a relationship and when it should be a Node?
For example, in the Movies Database,there is a relationship showing who acted in which film. A property of that relationship is the Role. BUT, what if it's a series of films? The role may well be constant between films (say, Jack Ryan in The Hunt for Red October, Patriot Games etc.)
We may also want to have some kind of Character bio, which would obviously remain constant between movies. Worse, the actor may change from one movie to another (Alec Baldwin then Harrison Ford.) There are many others like this (James Bond, for example).
Even if the actor doesn't change (Main roles in Harry Potter) the character is constant. So, at what point would the Role become a node in its own right? When it does, can I have a 3-way relationship (Actor-Role-Movie)? Say I start of with it being a relationship and then, down the line, decide it should've been a node, is there a simple way to go through the database and convert it?
No there is no way to convert your datamodel. When you start your own Database first take time to find a fitting schema. There is no ideal way to create a schema and also there are many different models fitting to the same situation without being totally wrong.
My strategy is to put less information to the relationship itself. I only add properties that directly concern the relationship and store all the other data in the nodes. Also think of properties you could use for traversing the graph. For example you might need some flags or even different labels for relationships even they more or less are the same. The apoc.algo.aStar is only including relationshiptypes you want (you could exclude certain nodes by giving them a special relationshiptype). So keep that in mind that you take a look at procedures that you might use later.
Try to create the schema as simple as possible and find a way to stay consistent in terms of what things are nodes and what deserves a relationship. Dont mix it up.
Choose a design that makes sense for you! (device 1)-[cable]-(device 2) vs (device 1)-[has cable]-(cable)-[has cable]-(device 2) in this case I'd prefer the first because [has cable] wouldn't bring anymore information. Irrespective to what I wrote above I would have a lot of information in this [cable] relationship but it totally makes sense for me because I wouldnt want to search in a device node for cable information.
For your example giving the role a own node is also valid way. For example if you want to espacially query which actors had the same role in common I'll totally go for giving the role a extra node.
Summary:
Think of what you want to do with the data and choose the easiest model.

CoreData Selecting All Rows in Association One-by-one When Persisting to Disk

I'm using a parent-child MOC architecture as described by Marcus Zarra in his blog post and talk.
It's generally working great, but I have an ordered one-to-many relationship where the "many" accumulates a lot of records over time. The issue is, in the process of saving the private context to disk, CoreData runs a select query for what appears to be every single object in the association, one at a time, even if it hasn't been touched. As you can imagine, this is incredibly slow.
Any ideas on how to eliminate this or at least make it batch it into one query?
Ordered relationships are problematic for a number of reasons, but this is out of scope for this question.
One obvious solution attempt is to replicate the ordered property yourself by introducing your own attribute to keep track of the order. This is the path I have taken in all my projects where I had this use case. Your own ordering logic gives you much more granular control over the expensive processes, such as inserting an element into the series (rather than just appending it at the end).
Please note that in many applications the ordered property can be modeled differently, e.g. with a time stamp, which in some cases can spare you the necessity of modifying the whole chain.
As for the problem of using "one query": You could fetch all objects needing to be reordered, modifying their order (e.g. by adding them one by one to the parent object), and save.

"Ordered lists" and bi- vs. uni-directional relationships

I'm a Neo4j newbie, just playing around in the browser modelling data for a project at the moment.
Here's my use case: A user can have a bunch of items. Each item is described by a storyline.
(:User)-[:OWNS]->(:Item)<-[:DESCRIBES]-(:Storyline)
No issues so far. However, the storyline needs to contain "cards", basically chapters of the story that need to be in order. So, my first thought was this.
(:Storyline)<-[:FOLLOWS]<-(a:Card)<-[:FOLLOWS]-(b:Card)
However, if we start at Card B, we now have to follow the path back to see what storyline/item the card belongs to. Seems inefficient. Would it be better to do this?
(a:Card {order: 0})-[:BELONGS_TO]->(:Storyline)
(b:Card {order: 1})-[:BELONGS_TO]->(:Storyline)
Or, might I even trash the Storyline and just have the following?
(:Card {order:0})-[:DESCRIBES]->(:Item)
Next, a user should be free to create a link to another storyline card belonging to his own or any other user's item.
(storyA:Card)-[:LINKS_TO]->(storyB:Card)
However, the owner of storyB may or may not want to link back to the first guy's story. I know you can ignore the direction of the relationship in a cypher query by doing:
(a)-[r]-(b)
But I read that explicitly creating bi-directional relationships is usually a bad idea. So if storyB wants to link back, how would you best represent this in the data model? Maybe another relationship type, like :LINKS_MUTUALLY or something, or a "mutual" boolean property on the :LINKS_TO relationship?
Regarding you first issue, it's usually better to have relationships rather than properties in this case.
I'd throw in FIRST and LAST relationships, like in this TimeTree, and model it as:
(a:Card)-[:DESCRIBES]->(i:Item)
(b:Card)-[:DESCRIBES]->(i:Item)
(c:Card)-[:DESCRIBES]->(i:Item)
(a:Card)<-[:FOLLOWS]-(b:Card)
(b:Card)<-[:FOLLOWS]-(c:Card)
(a:Card)<-[:FIRST_CARD]-(i:Item) //optional, for easy navigation
(c:Card)<-[:LAST_CARD]-(i:Item) //optional, for easy navigation
As for bidirectional relationships, the only are a bad idea if a relationship in one direction implies the other one. In your case, this is not the case, so creating (storyA:Card)-[:LINKS_TO]->(storyB:Card) and (storyA:Card)<-[:LINKS_TO]-(storyB:Card) is perfectly fine, since each relationship is there for a different reason.

ios UITableView with fetchedresultscontroller - add custom rows

I have a UITableView with data coming from NSFetchedResultsController.
Here is my tablewView:
I need to add a row "All types". It also needs to be:
Sortable with all other items
Selectable (Design is now selected)
Selecting "All types" should deselect other rows
Give something to understand that it's an "All types" row when selected
I've read Add extra row to a UITableView managed by NSFetchedResultsController and NSFetchedResultsController prepend a row or section. Given approaches makes impossible to sort data or will look so hacky and produce so much hard-maintailable code, that it will be impossible to change logic and maintain code.
Are there any other good options?
PS. I understand, that my question may sound "broad" and doesn't containt code, but I think it's very common problem.
I do not think this is a very common problem at all. I can see it seems natural to do what you are trying but lets analyse your situation: What you generally have are 2 arrays of objects which you wish to sort as a single array. Now that is quite a common situation and I believe everyone knows how to solve this issue. You need to create a single array of objects and then sort it.
The way I see it you have 3 options:
Fetch all the items, merge the 2 arrays, sort and present them. This is not a very good idea since your memory consumption can be a bit too large if there are a lot of items in the database.
Put the extra data into the database and use a fetch result controller as you would normally. This should work good but you will probably need to mark these items so they are later removed or keep it in the database but ignore them where you wish not to display them.
Create a temporary database combined with what needs to be fetched from the database and your additional data. This approach is great if your data are meant for read-only in this list (which actually seems to be the case in what you posted). Still it is best if you create some kind of link between the objects. For instance some kind of ID would be great, this way when user selects an object from the second database you simply read the ID and fetch the object from the original database.

Question about OOP and objects

I have a school assignment: a Dog Show.
My assignment is to create a website, where vistors can display results, and where Judges and Secretary can admin and CRUD.
I have a small problem, one part of the assignment: the result should be based on two decisions from different judges, and after that checked by the secretary, before the result is displayed for the user.
I have to say I'm fairly new to programming, and so I need some smart suggestions on how to design and implement this. The assignment should cover both a DB and C# (.NET MVC).
Q1: How do i create a object (result) that depends on two other objects (judge's decisions)? Is that even needed?
Q2: How to solve this in a relational db?
I don't think this would be hard to solve using a relational DB. I'd suggest that you consider each table in the database as representing an entity (class) in your object model. Some entities that you might want to consider Dog Show, Dog, Entry, Judgement, Result, Judge, Secretary (Judge/Secretary might both be an Official). According to your definition, each Entry would have 2 Judgements (thus you should have a 1-to-Many relationship there), but each Entry only has 1 Result. You might use code or a database constraint (or both) to ensure that a Result for an Entry isn't created until there are two Judgements for that Entry. Likewise, you might use code/constraint to ensure that no more than two Judgements are entered for each Entry.
Hope this helps get you started.
How do i create a object (result) that depends on two other objects (judge's decisions)? Is that even needed?
I suggest that you create the result object, when you create the 2nd decision object.
The pseudocode might be something like, when the judge tries to create a new decision, then see how many other decisions already exist:
case 0: this is the first decision; just create the new decision and return
case 1: this will be the second decision; create the new decision, and then create the result based on the two decisions
case 2 or more: two decisions already exist, so don't allow this further decision to be created.
Another (perhaps not so good) possibility is to have a separate "create results" process, which runs continually (not continuously: e.g., once every minute), looking for any already-created decision-pairs for which there's no corresponding result, and creating the corresponding result.

Resources