Doctrine2 and database-side triggers for denormalized fields - doctrine-orm

Let's say I have two tables: Category and Product, and Product links to Category with a foreign key Production.categoryId == Category.id. I would like my database server to take care of counting number of products within a category using a denormalized field Category.productCount - the triggers will update this count on any update/delete/insert, so I don't have to worry about it. Is there a way to synchronize database-side triggers with Doctrine2 entities somehow? I really don't want to recalculate those counters on PHP side, as we are going to run it on multiple servers.

If I understand the question you want to be able to add a new product to a category, persist it then have Category.productCount update itself from the database? You can use
$entityManager->refresh($category);
To reload an entity from the database. I have not done it myself but I would expect that you could use the life cycle functionality to automate this.
But I do kind of wonder if it might not be better to just increment the counter locally without persisting it to the database. Let your trigger do the database operation but, within the request, update the count locally.

Related

Django create or update model only if field not equal to certain value

We have a potential race condition where multiple users can try to create or update a record. Wondering if there's a way to create a column, than when set (to say true), then an exception will be thrown, preventing the update.
The underlying database is postgres, but since we're using django to wrap it, we would like to limit ourselves to something django offers, and not mess with very specific database settings. Thanks!

Handling multiple users concurrently populating a PostgreSQL database

I'm currently trying to build a web app that would allow many users to query an external API (I cannot retrieve all the data served by this API at regular intervals to populate my PostgreSQL database for various reasons). I've read several thing about ACID and MVCC but still, I'm not sure there won't be any problem if several users are populating/reading my PostgreSQL database at the very same time. So here I'm asking for advice (I'm very new to this field)!
Let's say my users query the external API to retrieve articles. They make their search via a form, the back end gets it, queries the api, populates the database, then query the database to return some data to the front end.
Would it be okay to simply create a unique table to store the articles returned by the API when users are querying it ?
Shall I rather store the articles returned by the API and associate each of them to the user that requested it (the Article model will contain a foreign key mapping to a User model)?
Or shall I give each user a table (data isolation would be good but that sounds very inefficient)?
Thanks for your help !
Would it be okay to simply create a unique table to store the articles returned by the API when users are querying it ?
Yes. If the articles have unique keys (doi?) you could use INSERT...ON CONFLICT DO NOTHING to handle the (presumably very rare) case that an article is requested by two people nearly simultaneously.
Shall I rather store the articles returned by the API and associate each of them to the user that requested it (the Article model will contain a foreign key mapping to a User model)?
Do you want to? Is there a reason to? Do you care who requested each article? It sounds like you anticipating storing only the first person to request each article, and not every request?
Or shall I give each user a table (data isolation would be good but that sounds very inefficient)?
Right, you would be hitting the API a lot more often (assuming some large fraction of articles are requested more than once) and storing a lot of duplicates. It might not even solve the problem, if one person hits "submit" twice in a row, or has multiple tabs open, or writes a bot to hit your service in parallel.

Conditional Relationships between Two Tables in Django?

The following image shows a rough draft of my proposed database structure that I will develop for Django. Briefly, I have a list of ocean Buoys which have children tables of their forecast conditions and observed conditions. I'd like Users to be able to make a log of their surf sessions (surfLogs table) in which they input their location, time of surf session, and their own rating.
I'd like the program to then look in the buoysConditions table for the buoy nearest the user's logged location and time and append to the surfLog table the relevant buoyConditions. This will allow the user to keep track of what conditions work best for them (and also eventually create notifications for the user automatically).
I don't know what the name for this process of joining the tables is, so I'm having some trouble finding documentation on it. I think in SQL it's termed a join or update. How is this accomplished with Django?
Thanks!

Django REST Framework as backend for tracking user history

I'm trying to track user history using a DRF backend. For that, I've created a history table that will get a new timestamped row with each update. This model is a many-to-one and has a reference to the user model by a foreign key.
Here comes the confusing part. Every time I pull up the user profile, I would like to also pull the last entry into the history table. Thus, I am considering adding a couple of columns in the table which get updated with every insert into the history table since this is probably less expensive than performing a secondary lookup each time. I'd like some feedback on this approach.
Additionally, I'm slightly confused by how to perform this update/insert combination via a single API endpoint as DRF seems to only support one-to-one CRUD.
For illustrative purposes, I'd like to achieve the following via a single API view:
User hits API endpoint with access token and update values --> Insert history table --> update user table for user's row with inserted details
Thanks!

Warehousing records from a flat item table: Django Signals or PostgreSQL Triggers?

I have a Django website with a PostgreSQL database. There is a Django app and model for a 'flat' item table with many records being inserted regularly, up to millions of inserts per month. I would like to use these records to automatically populate a star schema of fact and dimension tables (initially also modeled in the Django models.py), in order to efficiently do complex queries on the records, and present data from them on the Django site.
Two main options keep coming up:
1) PostgreSQL Triggers: Configure the database directly to insert the appropriate rows into fact and dimensional tables, based on creation or update of a record, possibly using Python/PL-pgsql and row-level after triggers. Pros: Works with inputs outside Django; might be expected to be more efficient. Cons: Splits business logic to another location; triggering inserts may not be expected by other input sources.
2) Django Signals: Use the Signals feature to do the inserts upon creation or update of a record, with the built-in signal django.db.models.signals.post_save. Pros: easier to build and maintain. Cons: Have to repeat some code or stay inside the Django site/app environment to support new input sources.
Am I correct in thinking that Django's built-in signals are the way to go for maintaining the fact table and the dimension tables? Or is there some other, significant option that is being missed?
I ended up using Django Signals. With a flat table "item_record" containing fields "item" and "description", the code in models.py looks like this:
from django.db.models.signals import post_save
def create_item_record_history(instance, created, **kwargs):
if created:
ItemRecordHistory.objects.create(
title=instance.title,
description=instance.description,
created_at=instance.created_at,
)
post_save.connect(create_item_record_history, sender=ItemRecord)
It is running well for my purposes. Although it's just creating an annotated flat table (new field "created_at"), the same method could be used to build out a star schema.