Searching based on a changing value in Solr - solr

Imagine you're creating a website that allows people to search for rental cars based on price, amongst other things. Some rental cars are more popular at certain times of the year than others, so their price varies based on date. For instance, a car might cost $90/day most of the year except for December & March, when it costs $110/day, and in January & February it costs $130/day. Is it possible to have a calculated field in Solr, so you can search for a car that costs less than $X/day over the duration of your rental? I'm new to Solr, so have absolutely no idea whether this is possible or not - sorry if I'm asking a dumb question.
One possibility that I've come across would be to index the item once for each price, and have start and end dates for each of these. This copes with the price changes, but won't work for rentals that cross price boundaries; for example, a customer might want to rent a car for one week in February and two weeks in March - we'd end up not finding the car in this case.
I'm using Solr 3.5. Is it possible to do this using a FunctionQuery? I've seen some documentation on them, but all the examples I've seen are using them to return a computed value, rather than performing a search on that computed value. If I can't do this using a FunctionQuery, how could I do it?

I think this might be possible:
In your index you can have different types of columns containing the different prices of different seasons. In your query, you need need to use a product on the price during a certain season against the number of days in that season, and sum it to the product on the price during the other season against the number of days in that season. Yes, you'll have to use FunctionQuery. The means of providing how many days falls into which season that you'll probably have to do on the client that is calling the solr web service. Furthermore, you can try to apply a filter query on the result to pick out the amount that the user is willing to pay.

Related

How do I persist sales price in an orders details table?

I'm writing a simple transactional database to practice my T-SQL skills.
If I sell an umbrella in my sales.orderdetails table and it's getting the current retailprice of that umbrella from the items table and putting it in the invoice, how do I keep from having incorrect historical report data 6 months from now when I jack up the retail price of the umbrella by $10?
How do i store that umbrella sold price in the orderdetails table so it's unaffected by any changes in the items table in the future?
I know you can use an SCD for a datawarehouse for this kind of issue but was wondering how to do it in an OLTP system. Computed persisted column? Can't seem to get that to work in the object explorer when I try to enter the items.retailprice as the computed value for the salesorderdetails.cost column.
The way I have seen this done in the past, without using a technique like SCD, was to have the order detail have the price that was charged and then use a foreign key to another table, possibly products or productprices, that contains the current price.
In a full-on transactional system, you'd want the order detail row to record full retail (MSRP, or what have you), current price (in case you had the item posted at a discount that day), and price charged (in case the customer used a promo/coupon code to reduce the price themselves). Unless you log all three, you're at the mercy of whatever the price changes to tomorrow or next week or next year, which makes for bad analytics.
You probably also want to capture current cost of goods, too, since that's subject to change over time, especially in an average costing scenario. Otherwise, margin calculations will be suspect.
But then, yes, a foreign key or keys to any other descriptive tables for those less ephemeral characteristics of the product.

Database Design for a Person's Availability

I am currently working on a web application that stores information of Cooks in the user table. We have a functionality to search the cooks from our web application. If a cook is not available on May 3, 2016, we want to show the Not-Bookable or Not-Available message for that cook if user performs the search for May 3, 2016. The solution we have come up to is to create a table named CooksAvailability with following fields
ID, //Primary key, auto increment
IDCook, //foreign key to user's table
Date, //date he is available on
AvailableForBreakFast, //bool field
AvailableForLunch, //bool field
AvailableForDinner, //book field
BreakFastCookingPrice, //decimal nullable
LunchCookingPrice, //decimal nullable
DinnerCookingPrice //decimal nullable
With this schema, we are able to tell if the user is available for a specific date or not. But the problem with this approach is that it requires a lot of db space i.e if a cook is available for 280 days/year, there has to be 280 rows to reflect just one cook's availability.
This is too much space given the fact that we may have potentially thousands of cooks registered with our application. As you can see the CookingPrice fields for breakfast, lunch and dinner. it means a cook can charge different cooking rates for cooking on different dates and times.
Currently, we are looking for a smart solution that fulfils our requirements and consumes less space than our solution does.
You are storing a record for each day and the main mistake, which led you to this redundant design was that you did not separate the concepts enough.
I do not know whether a cook has an expected rate for a given meal, that is, a price one can assume in general if one has no additional information. If that is the case, then you can store these default prices in the table where you store the cooks.
Let's store the availability and the specific prices in different tables. If the availability does not have to store the prices, then you can store availability intervals. In the other table, where you store the prices, you need to store only the prices which deviate from the expected price. So, you will have defined availability intervals in a table, specific prices when the price differs from the expected one in the oter and default meal price values in the cook table, so, if there is no special price, the default price will be used.
To answer your question I should know more about the structure of the information.
For example if most cooks are available in a certain period, it could be helpful to organize your availability table with
avail_from_date - avail_to_date, instead of a row for each day.
this would reduce the amount of rows.
The different prices for breakfast, lunch and dinner could be stored better in the cooks table, if the prices are not different each day. Same is for the a availability for breakfast, lunch and dinner if this is not different each day.
But if your information structure makes it necessary to keep a record for every cook every day this would be 365 * 280 = 102,200 records for a year, this is not very much for a sql db in my eyes. If you put the indexes at the right place this will have a good performance.
There are a few questions that would help with the overall answer.
How often does availability change?
How often does price change?
Are there general patterns, e.g. cook X is available for breakfast and lunch, Monday - Wednesday each week?
Is there a normal availability / price over a certain period of time,
but with short-term overrides / differences?
If availability and price change at different speeds, I would suggest you model them separately. That way you only need to show what has changed, rather than duplicating data that is constant.
Beyond that, there's a space / complexity trade-off to make.
At one extreme, you could have a hierarchy of configurations that override each other. So, for cook X there's set A that says they can do breakfast Monday - Wednesday between dates 1 and 2. Then also for cook X there's set B that says they can do lunch on Thursday between dates 3 and 4. Assuming that dates go 1 -> 3 -> 4 -> 2, you can define whether set B overrides set A or adds to it. This is the most concise, but has quite a lot of business logic to work through to interpret it.
At the other extreme, you just say for cook X between date 1 and 2 this thing is true (an availability for a service, a price). You find all things that are true for a given date, possibly bringing in several separate records e.g. a lunch availability for Monday, a lunch price for Monday etc.

Dimensional model to capture Sales weighting on different date schedules

We have a requirement to come up with a strategy to show Sales revenue data weighted by dates differently on different schedules.
We currently have a FactSales table with a grain of one row per order with the measure of sales amount. We have separate DimDate and DimTime dimensions,and a DimBusinessUnit dimension with one row for each entity within the organization.
In DimDate we have a flag for the major US holidays so we know reduced sales revenue may be expected. This flag would apply globally.
The ask is that different business units might have slow revenue days. For example, Monday's might be slow in one business unit, and Friday's slow in another. For analysis it is desireable to capture these different schedules with a flag or a weighting.
Ultimately this probably be reflected as a projected sales amount in a calculated measure.
How can I best add this weighting? Does it belong in the Date dimension, Business Unit dimension, or maybe a degenerate dimension in the Fact table, or something else altogether?
The DimDate is probably not a good place to keep this information, as each Business Unit (BU) may have a different schedule, so quite possibly you will have to have a flag on each of the dates per a combination of BU and a slow day. So for example if BU1 and BU2 has a slow day on Monday, each Monday in your DimDate will have to have a way showing that it's slow for BU1 and BU2.
The Dimension BU, might be a better place, as schedule is specific to each of the unit. So you may opt for extending your dim by adding 7 days as an attributes and flag them as slow or not using for example false or true flags. You could also have one attribute with the bit mask i.e. 0100000 where position of the value corresponds to the day i.e. M T W T F S S and 0 is not slow and 1 is slow, so in this example T is a slow day.
This will also allow you to trace a history if you whish selecting relevant SCD process.
Another option may be a separate Dimension i.e. DimSchedule and Factless Fact Table.
http://www.kimballgroup.com/data-warehouse-business-intelligence-resources/kimball-techniques/dimensional-modeling-techniques/factless-fact-table/
I hope this helps.
Your situation seems to be the same as the Multiple National Calendars problem described by Kimball:
http://www.kimballgroup.com/1998/12/think-globally-act-locally/
Where Kimball is describing holidays in the left-most table, you could also add a "slow day" flag.

How to store taxes in database?

I need to add per-province/state taxes to my project.
I'm debating whether I should add a many-to-many relationship between Provinces and Taxes, or just add a tax1_name, tax1_rate, tax2_name, tax2_rate to each province. I don't think any place has more than 2 taxes?
I will also need to store the tax rate at the time of purchase with each invoice.
So my options are add 2 many-to-many tables, or add 8 fields. Which would you go with, and why?
Or I could just have 1 combined tax. I don't think it would be too bad if it showed on the invoice as "GST + PST". This would solve the issue with stupid Quebec which charges QST on top of GST (tax on tax!).
Or I could just have 1 many-to-many table and store the start and end date of each tax and then when I generate the invoice I could look it up based on date.
What you really need is something like this:
The problem with combining the total tax into a single field is that while you may or may not get away with showing it that way on the receipt to a customer, the various jurisdictions are going to expect you and your accountants to track the tax collected and payable separately. Blended rates therefore won't do because you need the amounts broken out so you can pay the tax man and satisfy their auditors.
In my suggested solution to your problem, note that the TAX_RATE table includes an intersection between the tax and the jursidiction. This is so the rate can change, not only from jurisdiction to jurisdiction, but so that it can change over time.
Note too that the tax rate table includes a calculation_order value. This can be anything you like which can be sorted and compared. I've used integers before. The idea is that you apply the taxes in order starting with the first one. If you have two taxes that are applied to the same base amount, then these taxes have the same calculation order. If you pay tax two on top of tax one, then tax two has a higher calculation order.
Lastly, I've included a table that allows you to keep track of tax exemptions over time. You can handle this different ways and the way I've drawn it may not be the best or easiest. The point is to include a mechanism for saying "product X does (or doesn't) get tax Y (over a given date range)".
First, you must decide what the controlling dimensions for the taxrate are: state/province (does seller's or buyer's location apply ?), and time (year?) of transaction. These fields must become the keyfields for the tax-table lookup.
Also see the discussion here: How can I properly implement commerce data relationships in a sql database?

db design questions (how to deal with groups of products)

I would be grateful if somebody could help me to find an elegant solution to this database design problem. There is a company with a lot of different products (P1,P2,P3,P4) and a lot of customers (C1, C2, C3, C4). Now they have a simple database table to deal with orders, something like
20101027 C2 P1 qty status
20101028 C1 P2 qty status
Now I would like to create groups of products ( eg. (P1+P3+p4) and (P2+P3)) that could be purchase together for a reduced price. What is the best way to represent such groups in a database system? Dealing with these groups as individual products doesn't work, because I need the functionality of replacing, adding or removing products from the groups. So I need to keep the currently given table of products.
Thanks for reading. I hope I will get some help.
Add a new table product_group_promotions, with an ID, name and discount price. Then create a table product_group_promotions_products that links products to product group promotions. This will contain a product group ID and a product ID. This way, you can place one product in multiple groups, and let groups contain multiple products (of course).
Jan's answer is correct but incomplete.
You'll also need start and end dates of the promotion. You'll probably want to enter next week promotions so they are ready but not apply them until appropriate.
Discount price may not be enough either. You also will need to get business rules from business people as to how to apply the discount. It could be a percentage or a free item or a fixed amount. If a percentage do you distribute the discount evenly, proportionally, on the cheapest product, the most expensive? If a free item, which one in the set is free. It could also be a fixed amount, $10 off if you buy x, y, and z. Is the discount applied more than once. If someone buys 5x of P2 and P3 do they get the discount on all of them or just the first ones. Is there a limit over a time period. As in the past example, if you don't give me the discount on all 5, I would just fill out 5 orders of 1 each and get the discount you were trying to prevent. If so you'd have to go back through previous purchase by that customer to see if they've received that discount.
You can see how ugly this can get. I would clarify with the business EXACTLY what they plan to use this new feature for and run through these use cases with them.
As Q, asked, if the basket of purchased items is large enough there could be more than one discount possible. Do you have to determine what to give, do you present a list of choices back to the UI... and the recalculate.
This is why I have mercy on department stores who screw this stuff up. It's not simple.
On the surface this is simple sounding but in reality it's very complex.
"Dealing with these groups as individual products doesn't work, because I need the functionality of replacing, adding or removing products from the groups."
Here are several things you need to look at:
Current Inventory vs Past Orders
How do you deal with Price Changes on P1, P2, P3
How do you handle adding a new product or products to an existing group
How do you handle removing a product or products from an existing group
In my opinion you need two sets of tables.
Tables that make up your current inventory
Tables that record what customers purchased (historical data tables)
If you need to reconstruct a customers purchase from six months ago, you can not rely on the current data givin the fact that a grouping may not look the same today as it did six months ago. So, if you do not already have a set of historical data tables for customer records then, I recommend you create them.
With a set of historical data tables that house what was bought by the customer you can pretty much do what every you want to the current invetory data. Change prices, regroup products, make products obsolete, Temporarily suspend a product, etc.

Resources