Reference two tables that are related to each other - mysql

Imagine that I have these entities: Folder, Group, Document.
Now, each Folder has many Document's and these Document's can have a Group or not, inside that Folder.
So, a Folder would contain both grouped and ungrouped Document's.
How would I structure such relations?
I was thinking of two ways:
Document belongs to Group and Group belongs to Folder. This
requires me to always have an "ungrouped" Group for every Folder
(really ugly).
Document belongs to both Folder and Group, Group belongs to
Folder. This way I have the reference to the Folder and the
Group, where the group_id can be null to represent "ungrouped".
But this opens a door for error, by assigning a Document to a
Group/Folder where the Group doesn't belong to that Folder.
Neither solution seems right. This probably needs some kind of composite key and the Document would reference that.
What would be the proper way of doing this?

I would expect your second approach to give you the least headache in a real-world application. Although it might depend on specifics of the actual application.
One other alternative is to have groups not belong to folders (since it wasn't an explicit requirement), so that the same group_id might potentially span across various folders. Then you would interpret a pair (folder_id, group_id) as an actual group identifier in the Document table.

Related

Database Architecture Many-to-Many-to-Many

I have got an issue how to change a model of database:
For now we have predefined table Categories
and let's say tables Places and People which can be assigned to categories so it looks like this:
People <=> PeopleCategories <=> Categories <=> PlaceCategories <=> Places
(People can have many categories, categories can have many people, places can have many categories, categories can have many places)
But now there is a new requirement:
On person profile show all corresponding places based on categories (so far no problem) and add a tick box modeling some attribute (for example show on front-end as favorite place). The same from the other side on Place profile mark people assigned to at least one same category with a tick box.
I wonder whether there is some nice way to model this - the only thing which came to my mind is to add a new PeoplePlaces table but then I have to manually control whether people or places did not change their categories and they are still assigned and so on - There will be quite a problem with consistency of data which I will have to manage on application layer.
The second thing I could probably do is to delete categories totally and make it only on PeoplePlaces level but I will lose some simplicity for user: there are like 10 predefined categories which user can select so the linking between People and Places is quite automatic on front-end and only admin should see which places are assigned to which people and manage that tick box I was talking about
What would you suggest for this architecture? Thanks in advance! (It is a MySQL db if it is important for some kind of solution but this is more a general architecture thing)
If I understood your question correctly, you need to ensure that a person can only favor a place that is connected to the same category as the person herself?
If so, take a look at the following model:
We don't link the "endpoints" directly, and instead "link the links". This allows us to migrate PERSON_CATEGORY.CATEGORY_ID and PLACE_CATEGORY.CATEGORY_ID into the FAVORED_PLACE table, and "merge" them there, producing a single FAVORED_PLACE.CATEGORY_ID field (note FK1,FK2in the diagram above).
As a consequence, if a person is connected to a place, that must be done through a common category.
Furthermore, since CATEGORY_ID is outside PERSON_CATEGORY's PK, a particular combination of person and place can be used only once, even if they match through multiple categories. Effectively, you pick one common category as "special". If a place (or person) is removed from the special category, you'll need to pick another common category to serve as special. If there are no common categories left, the corresponding row in FAVORED_PLACE will not be allowed to exist anymore.
I don't think deleting Categories is a good idea.
What you are doing is introducing a new entity - PersonsFavouritePlaces - which relates People and Place directly rather than via a Category. It is sensible that a PersonsFavouritePlace be limited to a Person and a Place linked by Category, so it should probably reference PeopleCategories and PlaceCategories rather than the People and Category tables.
The table would look like:
create table PeopleFavourtiePlace
(
ID int not null, -- Primary key
PeopleCategoriesId int not null, -- FK to PK of PerpleCategories
PlaceCategoriesId int not null -- FK to PK of PlaceCategories
)
I don't know whether MySql supports cascading deletes, but if so the two FK's should have that turned on so when someone deselects a category (deleting the PeopleCategories row) if it linked to a favourite place in that category it too gets deleted.
However, if a person links to a place via multiple categories then it gets complicated....

Business Objects Reporting Standards

We are trying to set our BI team's reporting standards for Business Objects Universe Designer and Web Intelligence tools. We set some standars like below.
What are your ideas about these standards? Could you please share your standards documents?
Name the universe based on the application.
Give proper name universe objects (classes, dimensions, measures etc) according to
business terminology and being explicit in the definition. For
instance, an object called 'Sales' could be interpreted many
different ways. Is it Sales Revenue, Count of Sales Orders, Count of
Sales Order Lines, Average Sales Amount.
Company logo is put on the upperleft side of the report.
User prompts and last refresh time is put on the upper-right side of the report.
The title and report name describes the scope of the data (for example, university wide, unit specific, school/college level) and any conditions in the report (for example, term, fiscal year, department ID).
The columns of data are arranged in logical order.
When prompts are used, they model how the data should be entered. For example, “Enter the term (e.g. 1760)”
I think that this is a bit off topic for stackoverflow, and some of it is not clear or is commonsense anyway (eg. "columns of data arranged in logical order"), but I would suggest:
that every universe be associated with a three character code (eg. SAL, REV etc).
that every report be uniquely identifiable by a number, prefixed by the Universe code.
that non-trivial objects have as part of their definition a SQL-format comment giving their name and folder.
There two aspects :
Considering the technical aspect of the universe
Considering the end-user aspect of the universe
Technical aspects :
Layout of your tables should reflect your navigation
Version information/changes in either comment / hidden objects
try to use aliases as much as possible to show in what function your table is used.
try to refactor used constants in separate objects and use the #select to use them.
try to have a hierarchic naming convention so that the name will imply the navigation.
find a fitting naming convention for your connections.
User aspects :
DON'T DO THIS folder = table name , object = column name, it comes from dragging and dropping your tables.
object name is not literature, you are limited. It should be clear what the object is. Add comments always comments.
Limit number of folders, limit folder depth, limit number of objects in a folder.
Order the objects based on their use inside folder(most used on top).

mySQL store file details in one or many database table design and best way of creating parent and child categories

----- PHP and mySQL -----
I have two quick questions need some advice.
On my site I will allow users to upload following files - PDF/Videos/Photos. All files uploaded by the user are shown on a profile page. All uploaded files can be searched by name or tags and file type.
What would be the best mysql database design?
Store all files in one table, easier to display on user’s profile page and searching by type and etc.
One table per type e.g. pdf, videos and photos <- this might be better for performance but for searching I don’t know?
Second question is, I allow users to create their own menus/categories with parent and children categories for example:
->parent category
> child category
> child category
->parent category
> child category
> child category
At moment I have two database tables, one stores all the parent categories for each user and second store child category with foreign key (id) to parent category.
To get all the categories I first get all the parent categories and using a foreach loop.
I call a function within the loop to get the children categories by parent id.
I want to know is this the best approach of doing this or can this be done in mySQL query without looping?
thanks guys !!!
For your first question, it depends on what information you want to store about the files.
If it's generic across all types, (name, date, filetype, size, etc.) then a single Files table by itself with a type column makes sense.
But if you're going to save attributes of the files that have to do with what kind of file they are, frame rate of a video file, height and width of an image file, author of a PDF, for example, then you will also need some ancillary tables to store that information. You don't want to have a bunch of columns hanging off your file table that are only useful each for a certain file type.
For your second question, the rough SQL is based on a JOIN between your parent category table and your child category tables.
Example psuedo code:
select p.userid, p.parentcategoryid,c.childcategoryid
from ParentCategory p INNER JOIN
ChildCategory c
on p.parentcategoryid=c.parentcategoryid
WHERE
p.userid = #UserID

Mysql Folders and Documents

I want to have folders and documents which every one have a folder. Folders can have infinite children folders. What is the best mysql schema in your opinion.Do you think this is good?
Table Folders
id
name
parent (if null the root)
auth_user (access control type)
created_date
created_by
Table documents
id
name
type
idFolder (FK id of folders)
auth_user (access control type)
created_date
created_by
Do you think the above is good or gonna have problem later? Do you think with the above can get fast and easy the folders tree (i think with ORDER BY parent ASC can get the tree right)?
adjacency lists are nice for inserts and moving sub-trees but if you need to query deeper than one level it's pain in the a** because you will end up with n-joins if you go n-levels deep. An example: Show me all descendants/ancestors of Folder X.
I suggest to use the adjacency list (the parent_id) in combination with one of the following models:
Nested Sets
Materialized Paths
I really like the nested set - but it has a draw back - inserts are slow. But usually you will have more reads (browsing) the structure than inserting new nodes.
Another thing:
I usually put folders and documents in the same table and flag them with a boolean is_folder column. I like to think of folders/files as "nodes" in a tree so they're basically the same. Further metadata will be stored in another table.

DDD: refer to an entity inside an aggregate root by its identity

I'm stuck on finding the proper way to refer to entities located inside an aggregate root, when we only got their identities coming from URL parameters. I asked a previous question which ended up focused on value objects, so I'm starting with another example here.
Let's say we want to modify an OrderLine inside an Order:
The user goes to a page where he can see the Order summary along with all its Order Lines.
The user clicks on the edit button next to an Order Line.
He gets directed to edit-order-line?orderId=x&orderLineId=y
Now if I need to update the quantity in the OrderLine, I can do:
Order order = orderRepository.find(orderId);
order.updateQuantity(orderLineId, 2);
However, I don't feel very comfortable with the idea of leaving the responsibility to the Order to retrieve parts of itself by Id. My view on the subject is that within the domain, we should just talk with objects, and never with Ids. Ids are not part of the ubiquitous language and I believe they should live outside of the domain, for example in the Controller.
I would feel more confident with something like:
Order order = orderRepository.find(orderId);
OrderLine orderLine = em.find(OrderLine.class, orderLineId);
order.updateQuantity(orderLine, 2);
Though I don't like the idea of interacting directly with an Entity Manager, either. I feel like I'm bypassing the Repository and Aggregate Root responsibilities (because I could, potentially, interact with the OrderLine directly).
How do you work around that?
In my opinion there is nothing wrong with this approach:
Order order = orderRepository.find(orderId);
order.updateQuantity(orderLineId, 2);
orderLineId is a 'local identity'. It is specific to aggregate root and does not make sense outside of it. You don't have to call it an 'id', it can be 'order line number'. From Eric Evan's book:
ENTITIES inside the boundary have local identity, unique only within
the AGGREGATE.
...only AGGREGATE roots can be obtained directly with database queries. All other objects must be found by traversal of associations.
OrderLineId is what exactly? It has no meaning. You're updating the quantity of a PRODUCT and that's what should be used as the id.
Order order = orderRepository.find(orderID);
order.updateQuantity(productID, 2);
Aggregate Roots are bound to context, in your Context the Order is the AR so it is OK to update it directly since you are exposing it directly, if that code affects other entities they should live in the Order AR.
If you want a more purist approach you either have to make a findByOrderId in the AR and load it entirely or expose the OrderLine and OrderId in your application (then using your second approach).