issue with the usage of BELONGSTOMANY or HASMANY on sequelize - node.js

I've been using NODE.JS - SEQUELIZE to deal with POSTGRES database. But, it's been a while that I am facing an issue.
I have two TABLES:
FIRST TABLE: Purchases. Inside of this table, there is a column which keeps the foreign key of the Products table, because they are associated. But, as long as I'veen been coding, I realized that I needed to "insert" more than one products at once, like an array, for those people who will buy more than one product at once.
SECOND TABLE: Products.
I want something like this => Allow to a purchase inside of Purchases to have more than one products associated with. But all that I can do is make the product foreign key column in purchases table accepts only intenger (ID) of only one product.
For exemple:
The user X buyed multiple products, so then in product in Purchases will have the products [1,3,5] and these numbers are the product's ID that I would like to associate with the Products table.
print of the PURCHASES MODEL: purchases MODEL(not the migration) on sequelize
print of the PURCHASES TABLE: purchases table structure
print of the PRODUCTS TABLE: products table structure
The conclusion I've have reached was using "Belongs to MANY" or "Has many", but I don't how.
Thanks.

I propose you to add another table to achieve multiple products in one order:
ORDER table - stores one record per a customer order (all columns that related with an order as a whole)
ORDER_ITEMS - stores items inside each order (columns: a link to ORDER, a link to PRODUCT, a quantity, a price and other related columns (a discount and so on)
PRODUCT - stores a catalog of products to buy

Related

How to add product and product category in quotation pivot list in below list like sale analysis in odoo 11?

[in sale analysis on total two list product and product category there. same things I want to add in quotation pivot table how can I add?
That is not really possible, because the BI (Business Intelligence) reports (you called it "sale analysis" in your question) are actually transformed data with sales order LINES as base. And the pivot of sales order are based on sales order. You don't have product and product category information, because you have a one to many relation to order lines where this information is belonging to. It's only working the other way around (lines information -> order information).
So the solution is probably extending sale analysis (i think the model is sale.report) with every other thing you're missing there instead of changing the pivot of sales orders.

cassandra table modeling - updating existing columns in bulk and adding new columns

I am migrating RDBMS tables to cassandra. We track customers who are subscribing to different categories. There are some categories already but some categories maybe added new incourse of time. Right now we are joining the tables.
details table1 - columns
custid, name , address, phone
details table2 - custid, cat1, cat2, cat3, cat4
category details - catid, catname, catregion, catdescription, iscatmanadatory
In Cassandra I am trying to keep the customer id and name as primary keys. I am planning to keep categories subscribed by customer in a map. But if any new categories are added, will collection columns create any bottlenecks ?

Dynamic Grouping in Power BI/PowerPivot Model based on a calculated field

We are trying to create a model in Excel/Power BI (using Power Query or Power Pivot or anything that would work) in order to classify a customer by its best product (based on a ranking system).
The first approach we applied was to count the customers per minimum ranking (or per best product brand). (inspired from the blog https://stackoverflow.com/questions/15742186/powerpivot-dax-dynamic-ranking-per-group-min-per-group)
Below the steps we did exactly:
- In PowerPivot Model, we created Classification and Customers table like in the example further below.
In the same model, we added a calculated column with the following formula to obtain the minimum rank per customer.
=MINX (
FILTER ( ALLSELECTED ( Customers ); [Customer_ID] = EARLIEST ( [Customer_ID] ) );
[Ranking]
)
Within a pivot table in Excel, we’ve put the calculated column in rows.
Then, we’ve used a Count distinct aggregation of the customers in the pivot table values.
 This gave me the first desired result. (below example Pivot_Table.Selection1)
Now, the issue comes when we want to add more analysis axis.
For example, besides the product brand, we want to have the Product type in columns, and we want our measure to be recalculated every time I add/delete an axis.
In other words, we want to have a distinct customer count per best product and per Product Type.
In addition, we want the second attribute (axis) to be variable and the grouping or the distinct count per group to be dynamic.
Example:
Let’s suppose we have the tables Classification and Customers in our Model:
In the first approach we tried, we got the following table: Pivot_Table.Selection1:
Now when we add the analysis axis, we would like to have the following example: Pivot_Table.Selection2:
But we are having this:
As you can see, there should be one customer for the Group “Mercedes” and one for “Renault”, since depending on the product type, the top Truck for customer A is Renault and its top Car is “Mercedes”.
However, in the pivot table, the Mercedes group is shown as Truck (which doesn’t even exist in our dataset).
Edit
I'm open for any suggestion, not only Power Pivot, but also Power Query (M functions) or Power BI or whatever could work.
Finally I think I understood your problem, a customer can have different Product_Brand values, you want to count only those Product_Brand which its ranking is the minimum.
In that case, this is a possible solution:
Create a calculated column called Minimum Rank in the Customer table.
=
CALCULATE (
MIN ( [Ranking] );
FILTER ( Customer; [Customer_ID] = EARLIER ( Customer[Customer_ID] ) )
)
Then create a measure, lets say Customer ID Distinct Count to count those rows where the Rank is equal to the minimum for that customer.
Customer ID Distinct Count :=
CALCULATE (
DISTINCTCOUNT ( Customer[Customer_ID] );
FILTER ( Customer; [Ranking] = [Minimum Rank] )
)
You will get something like this:

DAX Rank by Date

I am Counting on Distinct ID's in a column - this is leading to the sum of the subtotals not equalling the grand total as follows:
What I want to do is rank the Payment Dates in cronological order and select ONLY the highest date to display. In the example above the Grand Total won't change, but the Townville row will not show a Distinct Student Count.
This is a very specific requirement and I'm assuming there's an easy way to do it in DAX - I've tried playing around with both RANKX and MAX but am no closer to solving this.
One last thing - the Rank must be contextual to the Time Filter selected by the user (so if they select 2015 it'd give the second record Rank 1 and the top record wouldn't show. If they select May 2015 it'd give the top record Rank 1 and the second record wouldn't show)
I think this is what you are looking for - I added a calculated column to the PowerPivot model that provides a rank based on the Last Payment Date and the Name of the Student. It will rank the earliest payment for any student as a 1.
The code for the column is as follows:
=RANKX(FILTER(Table1, [Student Name] = EARLIER([Student Name])), [Last Payment Date])
... assuming your table is named "Table1"!
The FILTER is the key that limits the ranking to dates belonging to students with that name only.
Update for Multiple tables
To set up relationships between the tables, go to the "Diagram View" of the model, available in the Home tab of the Power Pivot window.
You can drag fields from one table to the other to create relationships. This will only work if at least one of the fields is unique - it's a good idea to think of the model as a dimensional model, with a tables that acts like a fact and other tables around it that act like dimensions.
From the comment, I would try to get the Payments to act like the fact, and have it link to the Community and Student tables. in this case, you could then have the following code:
=RANKX(FILTER(Table1, Related('Students'[Student Name]) = EARLIER('Students'[Student Name])), [Last Payment Date])
This calculated column would be on your Payments Fact table, and it uses a lookup to a related field.
Note that in this specific case, it would be easier to just run the filter over your Student ID field that is used to lookup the Student name.

Cassandra data modeling

So I'm designing this data model for product price tracking.
A product can be followed by many users and an user can follow many products, so it's a many to many relation.
The products are under constant tracking, but a new price is inserted only if it has varied from the previous one.
The users have set an upper price limit for their followed products, so every time a price varies, the preferences are checked and the users will be notified if the price has dropped below their treshold.
So initially I thought of the following product model:
However "subscriberEmails" is a list collection that will handle up to 65536 elements. But being a big data solution, it's a boundary that we don't want to have. So we end up writing a separate table for that:
So now "usersByProduct" can have up to 2 billion columns, fair enough. And the user preferences are stored in a "Map" which is again limited but we think it's a good maximum number of products to follow by user.
Now the problem we're facing is the following:
Every time we want to update a product's price we would have to make a query like this:
INSERT INTO products("Id", date, price) VALUES (7dacedd2-c09b-46c5-8686-00c2a03c71dd, dateof(now()), 24.87); // Example only
But INSERT operations don't admit other conditional clauses than (IF NOT EXISTS) and that isn't what we want. We need to update the price only if it's different from the previous one, so this forces us to make two queries (one for reading current value and another to update it if necessary).
PD. UPDATE operations do have IF conditions but it's not our case because we need an INSERT.
UPDATE products SET date = dateof(now()) WHERE "Id" = 7dacedd2-c09b-46c5-8686-00c2a03c71dd IF price != 20.3; // example only
Don't try to apply a normal model on a cassandra database. It may work but you'll end up with terrible performance and scalability.
The recommended approach to Cassandra data modeling is to first figure out your read queries against the database and structure your data so that these reads are cheap. You'll probably need to duplicate writes somewhat but it's OK because writes are pretty cheap in Cassandra.
For your specific use case, the key query seems to be able to get all users interested in a price change in a product, so you create a table for this, for example:
create table productSubscriptions (
productId uuid,
priceLimit float,
createdAt timestamp,
email text,
primary key (productId,priceLimit,createdAt)
);
but since you also need to know all product subscriptions for a user, you all need a user-keyed table of the same data:
create table userProductSubscriptions (
email text,
productId uuid,
priceLimit float,
primary key (email, productId)
)
With these 2 tables, I guess you can see that all your main queries can be done with a single-row select and your insert/delete are straightforward but will require you to modify both tables in sync.
Obviously, you'll need to flesh out a bit more the schema for your complete need but this should give you an example on how to think about your cassandra schema.
Conditional update issue
For your conditional insert issue, the easiest answer is: do it with an UPDATE if you really need it (update and insert are nearly identical in CQL) but it's a very expensive operation so avoid it if you can.
For your use case, I would split your product table in three :
create table products (
category uuid,
productId uuid,
url text,
price float,
primary key (category, productId)
)
create table productPricingAudit (
productId uuid,
date timestamp,
price float,
primary key (productId, date)
)
create table priceScheduler (
day text,
checktime timestamp,
productId uuid,
url text,
primary key (day, checktime)
)
products table can hold for full catalog, optionally split in categories (so that listing all products in a single category is a single-row select)
productPricingAudit would have an insert with the latest price retrieved whatever it is since this will let you debug any pricing issue you may have
priceScheduler holds all the check to be made for a given day, ordered by check time. Your scheduler simply has to make a column range query on single row whenever it runs.
With such a schema, you don't care about the conditional updates, you simply issue 3 inserts whenever you update a product price even it doesn't change.
Okay, I will try to answer my own question: conditional inserts other than "IF NOT EXISTS" are not supported in Cassandra by the date, period.
The closest thing is a conditional update, but that doesn't work in our scenario. So there's one simple option left: application side logic. This means that you have to read the previous entry and perform the decision on your application. The obvious downside is that 2 queries are performed (one SELECT and one INSERT) which obviously adds latency.
However this suits our application because every time we perform a query to enqueue all items that should be checked, we can select the items urls and their current prices too. So the workers that check the latest price can then make the decision of inserting or not because they have the current price to compare with.
So... A query similar to this would be performed every X minutes:
SELECT id, url, price FROM products WHERE "nextCheckTime" < now();
// example only, wouldn't even work if nextCheckTime is not part of the PK or index
This is a very costly operation to perform on a Cassandra cluster because it has to go through all rows that are stored randomly in different nodes by default. Another downside is that we need some advanced and specific statistics regarding products and users.
So we've decided that a relational database will serve us better than Cassandra in this particular case.
We sadly leave all of Cassandra's advantages (fast inserts, easy scaling, built in sharding...) and look towards a MySQL Cluster or master-slave implementation.

Resources