Elasticsearch - Sum by quantity and sort by lowest price - elasticsearch

I have a requirement in Elasticsearch which I'm not able to implement at the moment. The use case is as follows; we have certain products uploaded in elastic (1 million + items) and each item has a quantity, a price and a lead time (for delivery).
Now I basically want to get the top matches (based on a product description search) where tot sum of all quantities = 1000 (example) sorted by the lowest price.
A similar but other query would be to get the top 1000 items with the lowest lead time.
Any recommendation on how to implement this and what the most performant way of doing this is?
Assume we have the following records:
Product 1 | Quantity 200 | price 4USD | lead time 2 days
Product 2 | Quantity 150 | price 3USD | lead time 5 days
Product 3 | Quantity 275 | price 5 USD | lead time 14
Now I want to get all products for a maximum of quantity of 200 with the cheapest items first. That would give me something like:
Product 2
Product 1
And then it would also give me some aggregates like the average delivery time for these 2 items is 3.5 days and total value is 650USD (150 x 3USD + 50 x 4 USD)
Thanks,
Bram

Related

Add multiple custom row measures in PowerBI

I have a PowerBi matrix and I'm trying to 3 some custom rows at the end of each group but can't figure out how to do so. Below is what the matrix looks like.
Salesperson
Total Units Sold
John
Apples
10
Oranges
5
Spoilage
2
Katie
Mangoes
12
Apples
9
Pears
15
Spoilage
1
And I'm trying to get a Total, Net and Percentage into the matrix as shown below. Total Fruits is a summation of all the rows above except the spoilage row. Net is the summation of all above including the Spoilage and Percentage (Pct) is Spoilage divided by Total Fruits.
Salesperson
Total Units Sold
John
Apples
10
Oranges
5
Total Fruits
15
Spoilage
2
Net
13
Pct
13.3%
Katie
Mangoes
12
Apples
9
Pears
15
Total Fruits
36
Spoilage
1
Net
35
Pct
2.9%
I have a fact table that records each fruit sold by the product code and the salesperson id and dimension tables for the salesperson and the products.
I'm new to PowerBI and so I would appreciate all the details to make this work.

DAX grand total "wrong" for price variance

I have repeatedly ran into the following problem when calculating variances, that the grand totals are calculated wrong. Although they are not technically wrong, I want to calculate them differently. The picture below shows what I have constructed in PowerPivot.
Formulas:
ACT Sales EUR = CALCULATE([Sales EUR];FILTER(data;data[Type] = "ACT"))
ACT Sales/kg = DIVIDE([ACT Sales EUR];[ACT Sales KG])
FC Sales/kg = DIVIDE([FC Sales EUR];[FC Sales KG]
Quantity Variance = ([ACT Sales KG] - [FC Sales KG]) * [FC Sales/kg]
Price Variance = ([ACT Sales/kg] - [FC Sales/kg]) x [ACT Sales KG]
The total variance is equal to column [Sales ACT vs FC EUR], but I would like the grand total for the variances to be a simple sum of the rows, and not using the measure formula on the grand total. How should this be done correctly?
The column structure for the data is as follows (where Type is either ACT, BUD, FC):
| Date | Type | Product | EUR | KG |
To fix variance totals, you need to iterate over product and then sum up the results:
Quantity Variance = (
SUMX(
VALUES( Data[Product]),
[ACT Sales KG] - [FC Sales KG]) * [FC Sales/kg]
)
(same for the other variance)

deciding discounts on set (which can be multiple) of products

I tried finding this question on SO over here but I dont find it relevant.
Let's say
1. Offer1 : buy 3 or more pencil and get 10% discount
2. Offer2 : buy 2 scale and 1 sharpener and get 20% discount on each set
so, a cart with pencil ($10) : 4 , scale ($20): 5, eraser($5): 1 and sharpener($10): 2 will look like:
Pencil : 4 Qty ==> $36 ($40 with 10% discount)
Scale: 2 Qty + Sharpener : 1 Qty ==> $40 ( $50 with 20% discount)
Scale: 2 Qty + Sharpener : 1 Qty ==> $40 ( $50 with 20% discount)
Eraser: 1 Qty ==> $5
Cart Total : $ 121 ( 36 + 40 + 40 + 5)
How to go ahead for implementing such algorithm ? Please guide me on this.
It should be a comment, but I don't have enough reputation points..so posting this way..
You can try below -
At the starting you have all the items and their corresponding prices.
Now create a method like calculatePrice_set1 which takes no of pencils and per pencil cost as parameters. Calculate total cost, if no of pencil more than 3 then substract discount and return the amount.
create another method calculatePrice_set2 which takes no of scale and sharpener and their corresponding cost. Now find how many set of 2 scales you have. Suppose you have passed 6 scales and 4 sharpeners as parameter. Then you have 3 set of 2 scales and 4 sharpeners. From this you can find how many eligible set for Offer2 you can make, which is 3 for this case. Calculate the total price for the set accordingly, apply discount and add left over pieces which couldn't be part of any set.
Then you can add return amount from step 1+ step 2+ (no. of eraser*price)

split quantities algorithm (stock exchanges order)

I have a problem where I have multiple (few thousand) quantities that I need to split between a set number of recipients such that each quantity must be split into whole numbers and using the same proportion.
I need to find an algorighm that implements this reliably and efficiently (dont we all ?:-) )
This is to solve a problem in financial markets (stock exchange orders) where an order might get thousands of "fills" and at the end of the day must be distributed to a few clients while maintaining the order's average price. Here's an example:
Total Order Quantity 37300
Quantities filled by the Stock Exchange
Execution 1. 16700 shares filled at price 75.84
Execution 2. 5400 shares filled at price 75.85
Execution 3. 4900 shares filled at price 75.86
Execution 4. 10300 shares filled at price 75.87
Total 37300 shares filled at average price = (16700*75.84 + 5400*75.85 + 4900*75.86 + 10300*75.87) / 37300 = 75.85235925
Suppose I need to split these quantities between 3 clients such that :
Client1: 15000 shares
Client2: 10000 shares
Client3: 12300 shares
Each execution must be split individually (I can't just take each clients requested quantity priced at average price)
My first thought was to split each proportionately :
Client 1 gets 15000/37300=0.402144772
Client 2 gets 10000/37300=0.268096515
Client 3 gets 12300/37300=0.329758713
Which would lead to
Client1 - 15000 Client2 - 10000 Client3 - 12300
Ratio : 0.402144772 Ratio : 0.268096515 Ratio : 0.329758713
Splits (Sorry about the formatting - this was the best I could do in the Post editor)
+-------------+-------------+-------------+
| Client 1 | Client 2 | Client 3 |
+-------------+-------------+-------------+
| 6715.817694 | 4477.211796 | 5506.970509 |
| 2171.581769 | 1447.72118 | 1780.697051 |
| 1970.509383 | 1313.672922 | 1615.817694 |
| 4142.091153 | 2761.394102 | 3396.514745 |
+-------------+-------------+-------------+
| Totals: | | |
| 15000 | 10000 | 12300 |
+-------------+-------------+-------------+
The problem with this is that I can't assign fractional quantities to clients so I need a smart algorithm which adjusts the quantities such that the fractional part of these splits is 0. I understand that this may be impossible in many scenarios so this requirement can be relaxed a little bit so that a certain client gets a little more (or less).
Does anybody know of an algorithm that I can use as a starting point for this problem ?
You can round all the numbers (ratio[n] * totalQuantity) except the last one (possibly the smallest) The last one must be the totalQuantity - sum of the others. This will give you whole number quantities while having a correct total as close to the ratios you choose.
Try to look at this from a different angle. You already know how many shares each client is getting. You want to calculate what's the fair total amount each has to pay and do this without rounding errors.
You therefore want this total dollar amounts to have no rounding issues, i.e. be accurate to the 0.01.
Prices can then be computed using the dollar amounts and displayed to the required precision.
The opposite (calculate prices, then derive amounts) will always yield rounding issues with the dollar amounts.
Assuming price is per 100 units, here's one way to accomplish this:
Calculate total $ for the order (16,700*75.84/100 + 5,400*75.85/100 + 4,900*75.86/100 + 10,300*75.87/100) = $28,292.93
Allocate all clients except 1, based on the ratio quantities ordered / quantities filled:
Client 2 = $28,292.93 / 37,300 * 10,000 = $7,585,24
Price = 7,585,24 / 10,000 * 100 = 75.8524.
Client 3 = $28,292.93 / 37,300 * 12,300 = $9,329.84
Price = $9,329.84 / 12,300 * 100 = 75.85235772
Calculate the last client as the remaining $$$:
$28,292.93 - ($7,585,24 + $9,329.84) = $11,377.85.
Price = $11,377.85 / 15,000 * 100 = 75.85233333
Here I arbitrarily picked Client 1, the one with the largest quantity to be the object of the remainder calculation.

How to optimize Cartesian product

Is there a better way to compute Cartesian product. Since Cartesian product is a special case that differs on each case. I think, I need to explain what I need to achieve and why I end up doing Cartesian product. Please help me if Cartesian product is the only solution for my problem. If so, how to improve the performance?
Background:
We are trying to help customers to buy products cheaper.
Let say customer ordered 5 products (prod1, prod2, prod3, prod4, prod5).
Each ordered product has been offered by different vendors.
Representation Format 1:
Vendor 1 - offers prod1, prod2, prod4
vendor 2 - offers prod1, prod5
vendor 3 - offers prod1, prod2, prod5
vendor 4 - offers prod1
vendor 5 - offers prod2
vendor 6 - offers prod3, prod4
In other words
Representation Format 2:
Prod 1 - offered by vendor1, vendor2, vendor3, vendor4
Prod 2 - offered by vendor5, vendor3, vendor1
prod 3 - offered by vendor6
prod 4 - offered by vendor1, vendor6
prod 5 - offered by vendor3, vendor2
Now to choose the best vendor based on the price. We can sort the products by price and take the first one.
In that case we choose
prod 1 from vendor 1
prod 2 from vendor 5
prod 3 from vendor 6
prod 4 from vendor 1
prod 5 from vendor 3
Complexity:
Since we chose 4 unique vendors, we need to pay 4 shipping prices.
Also each vendor has a minimum purchase order. If we don't meet it, then we end up paying that charge as well.
In order to choose the best combination of products, we have to do Cartesian product of offered products to compute the total price.
total price computation algorithm:
foreach unique vendor
if (sum (product price offered by specific vendor * quantity) < minimum purchase order limit specified by specific vendor)
totalprice += sum (product price * quantity) + minimum purchase charge + shipping price
else
totalprice += sum (product price * quantity) + shipping price
end foreach
In our case
{vendor1, vendor2, vendor3, vendor4}
{vendor1, vendor3, vendor5}
{vendor6}
{vendor1, vendor6}
{vendor2, vendor3}
4 * 3 * 1 * 2 * 2 = 48 combination needs to be computed to find the best combination.
{vendor1,vendor1, vendor6, vendor1, vendor2} = totalprice1,
{vendor1, vendor3, vendor6, vendor1, vendor2} = totalprice2,
*
{vendor4, vendor5, vendor6, vendor6, vendor3} = totalprice48
Now sort the computed total price to find the best combination.
Actual problem:
If the customer orders more than 15 products, and assume, each product has been offered by 8 unique vendors, then we end up computing 8^15=35184372088832 combinations, which takes more than couple of hours. If the customer orders more than 20 products then it takes more than couple of days.
Is there a solution to approach this problem in a different angle?
Your problem can get even more complex. A simple example:
Product 1 2 3
Vendor 1 10 20 40
Vendor 2 20 10 40
--------------------------
needed cnt 100 100 25
You need 100 El. of P1, 100 of P2, and 25 of P3.
P1 can be purchased for 1000 at V1, P2 for 1000 at V2, and P3 for 1000 at V1 or V3.
Now shipping would be free, if you purchase for 1500, but cost you 200 at each vendor else.
So if you order everything at V1, you would pay 4000:
1000+2000+1000+0 (shipping) = or for the same sum
2000+1000+1000+0 at V2, or splitted
1000+0+0+200 = 1200 at V1 plus
0+1000+1000+0 = 2000 at V2,
which sums up to 3200 and could be found by your method.
But you could split the purchase of product 3 this way:
1000+0+500+0 = 1500 at V1 plus
0+1000+500+0 = 1500 at V2
which only sums up to 3000 and would not be found by your method.
Afaik, there is established research in such topics, and the keywords are matrices and system of equations.
You can describe your problem as
f(c11, p11) + f(c22, p12) + f(c13, p13) = c1 => dc1
f(c21, p21) + f(c22, p22) + f(c23, p23) = c2 => dc2
...
f(c31, p31) + f(c32, p32) + f(c13, p33) = c3 => dc3
where cij is the count of product j at vendor i and pij is the price of product j at vendor i, but f(c11,p11) is not just count*price, but a function of count and price, since there might be a quantity discount. The right side is the purchase total for vendor i.
This is without purchase discount, which has to be modeled on top. If the discount on shipping is only depending on the total costs, it can be modeled just from ci => dci.
You would try to minimize sum (dc1+dc2+...+dcm).

Resources