1

I am building a personal app to store my notes in. It is not a new concept, of course, but it is giving me a great project to learn Node.JS together with trying out a graph database: Neo4j.

What I am having issues with, is coming up with a good data model for my app.

Requirements:

  • A note contains content in the form of text
  • Each note must have at least one tag connected to it
  • A tag can consist of one or more categories
  • I have to be able to search through the tags (connected categories)

An example:

  • Note: "Post Stack Overflow question"
  • Tag1: Personal -> develop -> Neo4j
  • Tag2: Personal -> develop -> Data design

Visual representation of the notes connected to categories: Visual representation of data

As you can see, two different notes share the same tag.

In MySQL I can use a many-to-many relation table to connect the categories together and to the note.

However a graph database is designed to overcome those relation tables if I understood correctly, so here is where I get stuck with my design.

I hoped to do it like this (not the same data as in example): Neo4j example

But this would never create unique connections between the notes and the tags, as I would want too.

I have the feeling I am missing one step...


The only thing I can come up with is:

  • Duplicating every category, but this will have a huge impact on the performance of the system and will generate a huge amount of (unneeded?) records.
  • Create an extra object in between the categories and notes, called tags, that connect the two together, but doesn't this defy the idea of the graph database?

How can I connect the hierarchical categories to a note in a Neo4j database?

1

I have read this question several times, and fundamentally, it seems to me that there appears some uncertainty about the function of Tags in the domain. In one place you show:

Tag1: Personal -> develop -> Neo4j

Here this looks as if the Tag1 contains an ordered list of categories.

Yet in the diagram that immediately follows this description, it looks more like Tags hold a bag of potentially independent Categorys.

Since it is fairly straightforward to arrange Categorys in various ways relative to each other, such as traditional hierarchy (like an org chart), or other kinds of hierarchy, we don't necessarily need Tags to help with that.

Further, we can assign a Note to multiple Categorys, also without using a notion of Tags.

So, what is it that you want Tags to offer? This is a question to ask of the domain; it is not a question of whether using SQL vs. Neo4j graph database vs. RFD triples.

Asking this question of the domain means understanding what users will see; what behaviors/manipulations they expect available. For example, for one, are Tags really needed/expected? For another, if we add a Category to a Tag (or otherwise update a Tag, do we expect all Notes sharing that Tag to be updated? (In other words, do Tags have some identity, or are they just values?)


Depending on the answers to the question of what Tags mean in the domain of interest, we can model them in either SQL using table or a graph database using nodes and relationships. It is not at all contrary to graph databases to introduce as many entities and relationships as needed to appropriately model the domain.

An advantage of graph databases is that we can store new relationship types without needing to create new relational tables, and we can search all the relationships without naming relational tables. This means that an existing query may find results in relationships that are newly added, something that wouldn't happen in a relational database, because the query would have to be updated to incorporate the new table. Still, we need to represent different kinds of information using different nodes and relationships; graph databases don't remove the need to have different entity types and different relationship types as required by the domain.


Sometimes, however, a graph database (and like RDF triples) can be limited, and this means introducing somewhat artificial solutions.

One example is representing (different) ordered collections of (the same), e.g. Categories. Keeping the various ordered collections separate from each other basically is a great use for ternary relationships, which are not supported in modeling systems that provide only binary relationships.

With Neo4j we might turn to the value attributes putting in an order number into the relationships that collect Categories (e.g. into a Tag). (If the extra operand of the ternary relationship is a node instead of a value, this won't work in Neo4j.) This (also) won't work in RDF since we can't attribute relationships with values, and instead will have to introduce a whole new triple (binary relationship).

In these situations, somehow we have to shoehorn all relationships into binary relations and this means creating an arguably somewhat unnatural entity to represent extra operands as a single element that can be referred to by a binary relationship. In these cases, there are somewhat arbitrary choices in how to do that, much like how compilers have multiple choices in how to compile high-level source code constructs to assembly language. For example, we can create an entity that represents two of the operands, then target that in a binary relationship. Alternatively, we can use a Davidsonian approach, which is that we create a "statement" entity, and grammatical verbs (relations), such as "Subject of" (not necessarily to be confused with yours), "Object of", the "Patient of". Then we can make multiple individual binary relationships describing the statement as a whole and representing its more complex relationship. An article on Davidsonian representation of complex staterments

This is why I consider modeling systems that don't have higher arity or higher order as more analogous to assembly language, requiring some method of translating more complex naturally occurring relationships. Good for machines to manipulate but not necessarily appropriate for direct human consumption.

Still, most relationships are binary, so a lot of things can be modeled in binary-only relationship systems without these complexities.

0
Note: "Post Stack Overflow question"
Tag1: Personal -> develop -> Neo4j
Tag2: Personal -> develop -> Data design

What about connecting Note directly to Neo4j and Data design? Then both can point to develop, and there is single connection between personal and develop.

As for search, you wont start with Note but with either Personal or develop or Neo4j|Data design and will get all connected subcategories and their posts. Because your search is a function of Category into Posts, so you can model your query after that ;)

When you display Note you do reverse for Category, you get Neo4j and Data design through connection and then collect all their super-categories.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.