How to design three dimension nosql database using Firebase - firebase

I am using Firebase as database for an e-commerce app.
I got a problem in the product catalog design.
My idea is:
1. One product can have different sizes. (e.g. S, M, L, XL)
2. One product can also have different colors. (e.g. black, blue, bronze, red)
3. The price can vary depends on different size OR different color, e.g. a medium size T-shirt in black is $100, while the same size T-shirt but in blue is $150.
In other words, there can be up to 9 different prices for one T-shirt which has 3 sizes and 3 colors.
Below is the design I can come up with.
I stored the sizes, colors, and the prices in the child 'sku'.
Under this child, I put the price for different color in the child 'price'
But I think it is not the best design so hope anyone could advise a better solution.
For security reason, I have hidden part of the unique key.

You should remodel your database according to your needs.
Products
|
-Kj53453453453453 //ProductId
| |
--- Small_Size: true
| |
--- Black_Color: true
| |
--- Quantity: 7
| |
--- Price: 100
| |
--- ProductId: T_SHORT_ID // which must be the same for all t-shirts of same type
|
-Kj53453794677886 //ProductId
|
--- XL_Size: true
|
--- Red_Color: true
|
--- Quantity: 9
|
--- Price: 65
|
--- ProductId: T_SHORT_ID // which must be the same for all t-shirts of same type
Sizes
|
--- Small_Size: "S"
|
--- Medium_Size: "M"
|
--- Large_Size: "L"
|
--- XL_Size: "XL"
|
--- XXL_Size: "XXL"
Colors
|
--- Black_Color: "Black"
|
--- Blue_Color: "Blue"
|
--- Bronze_Color: "Bronze"
|
--- Red_Color: "Red"
Using this model you'll be able to have a node for each product separately. This means, let say for the first product which has the -Kj53453453453453 as an id, you know that is back and the size si S. For this type of product you know also that you have 7 pieces. When someone is buying a piece, the only thing you need to do, is to decrease the quantity by one, that's it!
Creating the correct queries, you'll be able to display everything from your database, all products, all sizes, all colors, all products that are black, all products that have the size of XL and so on.
Hope iti helps.

Related

Application Insights chart is not respecting query order in a shared dashboard

The query is actually pretty simple:
traces
| extend SdIds = customDimensions.SdIds
| where isnull(customDimensions.AmountOfBlobStorageLoadedRows) == false
or isnull(customDimensions.AmountOfRowsAfterTransformation) == false
or isnull(customDimensions.AmountOfRowsIngestedToDW) == false
| summarize
BlobReadSum=sum(toint(customDimensions.AmountOfBlobStorageLoadedRows)),
TransformationSum=sum(toint(customDimensions.AmountOfRowsAfterTransformation)),
SavedToDWSum=sum(toint(customDimensions.AmountOfRowsIngestedToDW))
by tostring(SdIds)
| order by BlobReadSum desc, TransformationSum desc, SavedToDWSum desc
| limit 10
The following picture shows the application insights log tool. Like expected, the biggest values appear first in the chart:
However, the picture below shows the output of the same query, using the same time range, published to a shared dashboard:
What happened to the order?
Is there any setting that may interfere on this?
You could add | sort tostring(SdIds) after | order in the suffix of your query:
| order by BlobReadSum desc, TransformationSum desc, SavedToDWSum desc
| sort tostring(SdIds)
| limit 10
In azure log analytics dashboard parts there's an automatic sort for the x axis when its type is string.
You might notice that the chart sort in the dashboard would be just the opposite. In this case click "Open chart in Analytics" in the top right corner of your part, and change the desc/asc sort configuration of | sort tostring(SdIds) command.

Computing ARI by finding patterns in a reduced graph

I have a graph in which items can be partitioned differently, i.e. clusters of items vary between two partitions. I'd like to calculate the Adjusted Rand Index between two different partitions to evaluate how much they differ.
The graph
This is the general structure of the graph:
(:Store)-[:SELLS]->(:Product)-[:SIMILAR]-(:Product)<-[:SELLS]-(:Store)
--- red_beans ------ orange_beans ---
/ / \
supermart ------ yellow_beans --- --- ecomart
\ \ /
--- blue_beans ------ green_beans ---
--- blue_jello ---
/ \
supermart --- purple_jello --- --- ecomart
\ /
--- red_jello ---
Each store sells different colored products.
Each product from a store can be similar to products in another store.
Additionally, each store can bundle different products together:
(:Product)-[:BUNDLED]-(:Product)
purple_jello --- red_beans --- blue_beans (supermart bundle)
red_jello --- orange_beans (ecomart bundle)
The question
Regardless of product color (different colors of a product are considered to be the same product), for products available in both stores (similar products are actually the same product available in both stores), how much do bundles differ between stores?
The process
The first step would be to reduce the graph to correspond to the question. It should (virtually) look like this:
(:Store)-[:SELLS]->(:Product)-[:SIMILAR]-(:Product)<-[:SELLS]-(:Store)
supermart --- super_beans --- eco_beans --- ecomart
supermart --- super_jello --- eco_jello --- ecomart
I would like to reduce different colors of a product into one by looking at their indirect similarities. Products from a same store that are indirectly linked by similarity will be considered the same:
(a:Store)-[:SELLS]->(:Product)-[:SIMILAR*]-(:Product)<-[:SELLS]-(a:Store)
The bundles will also be simplified like this:
(:Product)-[:BUNDLED]-(:Product)
super_jello --- super_beans (supermart bundle)
eco_jello --- eco_beans (ecomart bundle)
This should be a natural extension of the products reduction. Multiple edges will also be reduced into one.
The second step would be to extract the information necessary to calculate the ARI between the different partitions of products. The ARI is:
Three measures are needed to compute it:
The number of product pairs that are found in both stores' bundles. Basically, the number of times this pattern is present in the graph:
(a:Store)-[:SELLS]->(:Product)-[:SIMILAR]-(:Product)<-[:SELLS]-(b:Store)
| |
[:BUNDLED] [:BUNDLED]
| |
(a:Store)-[:SELLS]->(:Product)-[:SIMILAR]-(:Product)<-[:SELLS]-(b:Store)
The number of product pairs that are found in one store's bundles. Basically, the number of times this pattern is present in the graph, for each store:
(a:Store)-[:SELLS]->(:Product)
|
[:BUNDLED]
|
(a:Store)-[:SELLS]->(:Product)
The number of possible product pairs in one store. Since we consider only products that are available in both stores, each store has the same number of products, and this would be:
MATCH (a:Store)-[:SELLS]->(p:Product)
RETURN a, count(p)*(count(p)-1)/2
The implementation
Implementing this into cypher queries isn't as natural as I expected. I am having trouble translating my process, especially the first step, and would appreciate any help.
Edit: This is the graph I am working on:
with [
{
store: 'supermart',
products: ['red_beans','yellow_beans','blue_beans','purple_jello',
'orange_icecream','pink_icecream','blue_candy','brown_cake']
},
{
store: 'ecomart',
products: ['orange_beans','green_beans','blue_jello','red_jello',
'red_icecream','white_icecream','purple_candy','white_sugar']
}
] as sells
unwind sells as sell
merge (s:Store {name: sell.store})
with s, sell
unwind sell.products as product
merge (p:Product {name: product})
merge (s)-[:SELLS]->(p);
with [
['red_beans', 'purple_jello'],
['red_beans', 'blue_beans'],
['blue_beans', 'purple_jello'],
['yellow_beans', 'brown_cake'],
['orange_icecream', 'pink_icecream'],
['pink_icecream', 'blue_candy'],
['orange_beans', 'red_jello']
] as bundles
unwind bundles as bundle
match (p1:Product {name: bundle[0]})
match (p2:Product {name: bundle[1]})
merge (p1)-[:BUNDLED]-(p2);
with [
['red_beans', 'orange_beans'],
['yellow_beans', 'orange_beans'],
['yellow_beans', 'green_beans'],
['blue_beans', 'green_beans'],
['purple_jello', 'blue_jello'],
['purple_jello', 'red_jello'],
['orange_icecream', 'red_icecream'],
['pink_icecream', 'red_icecream'],
['pink_icecream', 'white_icecream'],
['blue_candy', 'purple_candy']
] as similarities
unwind similarities as similar
match (p1:Product {name: similar[0]})
match (p2:Product {name: similar[1]})
merge (p1)-[:SIMILAR]-(p2);
The ARI for this graph is 0.571428

React native firebase 'average' query?

I come from a php/mysql background, and json data and firebase queries are still pretty new to me. Now I am working in React Native and I have a collection of data, and one of the keys stores a integer. I want to get the average of all the integers. Where do I even start?
I have used Firebases snapshot.numChildren function before so I am getting a little more familiar in this json world, but any sort of help would be appreciated. Thanks!
So, you know that you can return all of the data and determine the average. I'm guessing this is for a large set of data where it would be ideal not to return the entire node every time you would like to retrieve and average.
It depends on what this data is and how it's being updated, but I think one option is to simply have a separate node that is updated every time the collection is added to or is changed.
Here is some really rough pseudo code. For example, if your database looks like this:
database
|
+--collection
| |
| +--item_one (probably a uid like -k2jduwi5j5j5)
| | |
| | +--number: 90
| |
| +--item_two
| | |
| | +--number: 70
|
+--collection_metadata
| |
| +--average: 80
| |
| +--number_of_items: 2
Then when a new item is added, you run a metadata calculation:
var numerator = average * number_of_items + newItem.number;
number_of_items++; <-- this is your new number of items
numerator / number_of_items; <-- this is your new average
Then when an item is updated, you run a metadata calculation:
var numerator = average * number_of_items - changedItem.oldNumber + changedItem.newNumber;
numerator / number_of_items; <-- this is your new average
Now when you want this data, you always have this data on hand.

Retrieving data with dynamic attributes in Cassandra

I'm working on a solution for Cassandra that's proving impossible.
We have a table that will return a set of candidates given some search criteria. The row with the highest score is returned back to the user. We can do this quite easily with SQL, but there's a need to migrate to Cassandra. Here are the tables involved:
Value
ID | VALUE | COUNTRY | STATE | CITY | COUNTY
--------+---------+----------+----------+-----------+-----------
1 | 50 | US | | |
--------+---------+----------+----------+-----------+-----------
2 | 25 | | TX | |
--------+---------+----------+----------+-----------+-----------
3 | 15 | | | MEMPHIS |
--------+---------+----------+----------+-----------+-----------
4 | 5 | | | | BROWARD
--------+---------+----------+----------+-----------+-----------
5 | 30 | | NY | NYC |
--------+---------+----------+----------+-----------+-----------
6 | 20 | US | | NASHVILLE |
--------+---------+----------+----------+-----------+-----------
Scoring
ATTRIBUTE | SCORE
-------------+-------------
COUNTRY | 1
STATE | 2
CITY | 4
COUNTY | 8
A query is sent that can have any of those four attributes populated or not. We search through our values table, calculate the scores, and return the highest one. If a column in the values table is null, it means it's applicable for all.
ID 1 is applicable for all states, cities, and counties within the US.
ID 2 is applicable for all countries, cities, and counties where the state is TX.
Example:
Query: {Country: US, State: TX}
Matches Value IDs: [1, 2, 3, 4, 6]
Scores: [1, 2, 4, 8, 5(1+4)]
Result: {id: 4} (8 was the highest score so Broward returns)
How would you model something like this in Cassandra 2.1?
Found out the best way to achieve this was using Solr with Cassandra.
Somethings to note though about using Solr, since all the resources I needed were scattered amongst the internet.
You must first start Cassandra with Solr. There's a command with the dse tool for starting cassandra with Solr enabled.
$CASSANDRA_HOME/bin/dse cassandra -s
You must create your keyspace with network topology stategy and solr enabled.
CREATE KEYSPACE ... WITH REPLICATION = {'class': 'NetworkTopologyStrategy', 'Solr': 1}
Once you create your table within your solr enabled keyspace, create a core using the dsetool.
$CASSANDRA_HOME/bin/dsetool create_core keyspace.table_name generateResources=true reindex=true
This will allow solr to index your data and generate a number of secondary indexes against your cassandra table.
To perform the queries needed for columns where values may or may not exist requires a somewhat complex query.
SELECT * FROM keyspace.table_name WHERE solr_query = '{"q": "{(-column:[* TO *] AND *:*) OR column:value}"';
Finally, you may notice when searching for text, your solr query column:"Hello" may pick up other unwanted values like HelloWorld or HelloThere. This is due to the datatype used in your schema.xml for Solr. Here's how to modify this behavior:
Head to your Solr Admin UI. (Normally http://hostname:8983/solr/)
Choose your core in the drop down list in the left pane, should be named keyspace.table_name.
Look for Config or Schema, both should take you to the schema.xml.
Copy and paste that file to some text editor. Optionally, you could try using wget or curl to download the file, but you need the real link which is provided in the text field box to the top right.
There's a tag <fieldtype>, with the name TextField. Replace org.apache.solr.schema.TextField with org.apache.solr.schema.StrField. You must also remove the analyzers, StrField does not support those.
That's it, hopefully I've saved people from all the headaches I encountered.

How to show all variation prices on Shop Page?

I have products with variations, and each variation has a different price.
Right now I have the product with the minimum variation price showing like this:
--------
| ** |
| ** |
--------
The orange box
From: 99$
What I want is this:
--------
| ** |
| ** |
--------
The orange box
Lite: 99$
Standard: 109$
Deluxe: 199$
New info:
With the help of this plugin, and editing it I have managed to get to this point:
--------
| ** |
| ** |
--------
The orange box
Lite:
Standard:
Deluxe:
But I'm, still missing the variation prices and there seems to be no documentation or implemented methods to get them easily.
Thank you.

Resources