I have two queries related to using the slots feature.
I created a slot that prompts the user to enter a number. so i used #sys-number and created a context variable $number to capture it. However i want to also check that the number enter by user is exactly 5 digits. is there a way to perform this validation?
in another scenario i have to prompt the user to provide 2 numbers – customer id and order id. both are numbers. so i again created 2 slots with #sys-number and created 2 context variables to capture customerId and orderId. now my problem is how to figure out order of these numbers in the user input. so let’s say that if the users writes “please give me status of my order with id 100”, how can i ensure that 100 is interpreted as the orderId and not customerId. At present because my first slot is customerId, watson assumes that the number provided is customerId and not orderId and it again prompts the user to provide customerId. is there a way to design it in a better way. i was hoping that if i can get answer to Point 1, may be i can put some check on number of digits and do something.
Looking forward for some tips here. thanks !
The first problem you can resolve as informed by chughts , using entities as a pattern (regex).
For the second problem, is a little more complex, but if the client does not inform customerid + orderid on the same input, then you can create a new entity with values like "order" and "customer" and use conditions to enter the slot or in the found of the slot, something like "if #sys-number && #type:order && !#type:customer". But the best solution would vary based on how things are asked and on how your clients respond.
If you need to treat inputs with but informations and there is no way to separate, the questions or reconfirm some information, the only thing i can imagine would be to use the positions of the entity to define for what information the #sys-number refer.
If the customerid and the orderid have different patterns (ex customerid have 6 numbers and orderid have 10 numbers), it's easier, you can just use patterns.
Personally, when i need to work with the system entities, i prefer to use single nodes or a "check for" that would never match, so i can test aways force to enter in the slot and test everything on the not found, but it depends on the needs.
Create a regex defined entity and use that instead of #sys-number.
Related
I am making a system similar to our Play Store's star rating system, where a product or entity is given ratings and reviews by multiple users and for each entity, the average rating is displayed.
But the problem is, whether i should store the ratings in database of each entity with a list of users who rated it and rating given, but it will make it hard for a user to check which entities he has rated, as we need to check every entity for user's existence,
Or, should i store each entity with rating in user database but it will make rendering of entity harder
So, is there a simple and efficient way in which it can be done
Or is storing same data in both databases efficient, also i found one example of this system in stackoverflow, when the store up and down votes of a question, and give +5 for up vote while - for down vote to the asking user, which means they definitely need to store each up and down vote in question database, but when user opens the question, he can see his vote, therefore it is stored in user's database
Thanx for help
I would indeed store the 'raw' version at least, so have a big table that stores the productid/entityid, userid and rating. You can query from that table directly to get any kind of result you want. Based on that you can also calculate (or re-calculate) projections if you want, so its a safe bet to store this as the source of truth.
You can start out with a simple aggregate query, as long as that is fast enough, but to optimize it, you can make projections of the data in a different format, for instance the average review score per product. This van be achieved using (materialized) views, or you can just store the aggregated rating separately whenever a vote is cast.
Updating that projected aggregate can be very lightweight as well, because you can store the average rating for an entity, together with the number of votes. So when you update the rating, you can do:
NewAverage = (AverageRating * NumberOfRatings + NewRating) / (NumberOfRatings + 1)
After that, you store the new average and increment number of ratings. So there is no need to do a full aggregation again whenever somebody casts a vote, and you got the additional benefit of tracking the number of votes too, which is often displayed as well on websites.
The easiest way to achieve this is by creating a review table that holds the user and product. so your database should look like this.
product
--id
--name
--price
user
--id
-- firstname
--lastname
review
--id
--userId
--productId
--vote
then if you want to get all review for a product by a user then you can just query
the review table. hope this solves your problem?
I am maintaining an Access Database for use with student admissions. I have a primary table which houses biographical information, and a secondary table which has application information, and allows for multiple applications per student (with each student having a unique student ID; that ID is stored in both tables and is how the applications are matched to the student).
Each application is assigned an "Application Number," and each student can only have one application with a specified number (i.e., student A cannot have two applications numbered "1", but can have 1, 2, and 3).
I would like to create a validation rule of some kind to prevent duplicates, but the whole column is not unique... it's only as it relates to the specified student.
Is there a way to create such a rule, or should I be arranging my data differently? I am open to making changes if it means a more efficient workflow.
I hope this makes sense... I wasn't sure how best to describe this. Thank you for any help.
If you are expecting the user doing the data entry to come up with a valid unique "application number", then the rule you are looking for would be a unique index on both StudentId and ApplicationNumber. (Remember, you can create an index which includes multiple columns.) This would mean that every pair of StudentId and ApplicationNumber must be unique.
However, I should note that requiring the user doing the data entry to have to come up with a unique application number by themselves is very user-unfriendly.
Consider the following alternatives:
Have the database suggest a unique application number. Or, better yet,
Do not even suggest any number while the application is being filled-in, but instead issue a unique application number at the moment that the application is submitted. Or, even better yet,
Stop storing application numbers in the database, and instead have the database calculate them, only when there is a need to display them, based on user id and date of data entry of the application. (Caveat: if a student has 3 applications, and application #2 gets deleted, then the old application #3 will be renumbered to #2, thus causing confusion. So, this will only work if deletion is disallowed.)
I'm looking for a way SQL Server can generate a unique identifier that is not an increment Int or a GUID.
The Unique ID can be a combination of letters and numbers and has no other characters, and as previously mentioned Must be Unique.
ie AS93K239DFAK
And if possible must always start with AS or end with an K
It would be nice if this unique id can be generated automatically when there is an Insert like GUIDs and IsIdentity = Yes does. It can be a random number, it is not predetermined in the app.
Is doing something like this possible, or does it have to be generated application-side?
From comments, it sounds like you would be OK with using an IDENTITY field and padding it with 0s and adding a prefix/suffix. Something like this should work:
1 - Add an IDENTITY field which will be auto-incremented
2 - Add a calculated field in the table with the definition of:
[InvoiceNo] AS ('AS' + RIGHT(('000000000' + CAST(idfield AS varchar(9))), 9) + 'FAK')
This will give you invoiceno in the format of:
AS000000001FAK
AS000000002FAK
...
AS000995481FAK
I've never seen a randomly generated invoice number. Most of them are usually a combination of multiple identifying fields. For example, one segment might be the companyID, another might be the InvoieID, and a third might be a Date value
For example, AS-0001-00005-K or AS-001-00005-021712-K, which would stand for CompanyId 1, Invoice #5, generated on 2/17/12
You said in a comment that you don't want to let the company know a count of how many past invoices there are, and this way they won't know the count except for how many invoices they have received, which is a value they should know anyways.
If you're concerned about giving away how many companies there are, use an alpha company code instead, so your end result looks like AS-R07S-00005-K or ASR07S00005K
So you can do it this way, just don't expect it to perform well.
(1) populate a big massive table with some exhaustive set of invoice values - which should be at least double the number of invoices you think you'll ever need. Populate the data in random order in advance.
(2) create a stored procedure that pulls the next invoice off the pile, and then either deletes it or marks it as taken.
But, be sure that this solution makes sense for your business. In many countries it is actually law for invoice numbers to be sequential. I'm guessing we're not really talking about invoices, but wanted to make sure it's at least considered.
What is so confusing about the random part being unique? If you have a two digit invoice number there can only be 100 unique values (00 - 99). A GUID has 2 to the power 128 values and is statistically unique. If you use a 8 characters of a GUID then with even 1 million invoices you have a betting chance of getting a collision. With 1 million invoices if you use 12 characters of GUID then you have very good chance of NOT getting a collision. If you use 16 characters of a GUID then you are pretty much statistically unique if you have less than 1 billion invoices. I would use 12 characters but check against actual values for uniqueness and you only have lottery chance of getting collision.
How are you inserting these new invoices to the table? A straight up batch insert or are you doing some business logic/integrity checks in a stored procedure first and 'creating' the invoices one by one?
In the second case, you could easily build a unique ID in the procedure. You could store a seed number in a table and take the number from there then cast it as a varchar and append the alphanumeric characters, you can then increment the seed. This also gives you the option of creating a gap between unique IDs if you needed to import some records into the gap at a later date.
Admittedly, I am simply looking for some direction here. I have a specific situation, and being a novice in database design I am lost on how to begin tackling this problem. Let me start by explaining my situation.
I have a mysql table called contacts. As the name infers, it stores a list of contacts and the attributes that go along with each such as first name, last name, email, phone number etc. I would like users of my application to be able to add an unlimited amount of certain attributes for each contact. So, for instance rather than a contact having one phone number, the user could add another number, and another if they choose etc so essentially, a contact in my database can have as many phone numbers as the user needs. This will also be true for other fields in the table, but for the sake of simplicity let's just stick with phone number as an example.
So what is the best way to approach this? Should I have a separate table called contactsPhone and have a matching id column so that any number of rows in the phone table can be associated with one row in the contacts table? Or is there a way to store an ArrayList of some sort in the contacts table so I can have multiple phone numbers in just one field?
You should be looking at modelling something like this in a document database - a relational database is a poor choice for a flexible schema. You may be able to just have this specific portion of you data in a document database.
If you must, the common solution is the entity-attribute-value pattern - note that this requires multiple joins, makes ad-hock queries difficult and is generally slow.
Update:
I misread the question a bit - if you do know which attributes you want to hold multiple values and this list will not change (or not change much), entity-attribute-value may not be the best way forward.
A one-to-many table per each of these attributes will work (and is a standard relational solution for this kind of problem) - each such table will require a foreign key to your contacts table and a column to hold a single attribute value. This allows you to have multiple attribute values against a single contact.
I would like users of my application to be able to add an unlimited
amount of certain attributes for each contact. So, for instance rather
than a contact having one phone number, the user could add another
number, and another if they choose etc so essentially, a contact in my
database can have as many phone numbers as the user needs.
You're not describing an unlimited number of attributes for each contact. (That's a Good Thing.) You're describing an unlimited number of rows for a single attribute, in this case a contact's phone number.
So, yes, a table of contact phone numbers would work well. You might want to give some thought to how the user might want to identify phone numbers. For example, do they need to distinguish home phone numbers from work numbers and so on.
I'm am making a system where a user can vote up or down on a product, I need to be able to explicitly work out the amount of ups and downs a product has, as well as a total score for a recent period.
Each vote can optionally have a comment with it, and users need the ability to echo/boost other peoples comments (kinda like a retweet), and this will also add/subtract the total score of the product depending on the parent vote being retweeted.
Here are my current proposed tables:
Product
ID, name, category_id
Vote
ID, user_id, product_id, parent_id, comment, score, datetime
User
ID, username etc.
I am thinking I will possibly need a comments table to do this effectively? The votes' score field is either 1 or -1 as per some advice I read on StackOverflow which would allow me to gather the SUM() of that column to calculate total votes, another possibility would be to have separate vote_up and vote_down tables...but I am just not sure.
Depending on what you want to do, this can be an incredibly sophisticated problem, but here's my take on the simplest way (eg. what i can throw together in the 10 min before I leave work ;-P)
I would try the StackOverflow/HotOrNot style approach, and Store their ranking as an unsigned integer.
PRODUCTS(
id,
category_id,
name,
rating INTEGER UNSIGNED NOT NULL DEFAULT 0
);
Then in your 'VOTES' table, you store the Vote (up/down). I think the table you have for your 'VOTES' table looks fine( although I would use either an enumeration as the SCORE datatype, or some strategy to ensure that a vote can't be manipulated via XSS. eg. someone modifies the vote so that their vote up is +10,000 instead of +1, then that would not be cool )
For a small fun app, you can probably get by with incrementing or decrementing the count when the user clicks, but if you are doing anything with aspirations of scaling out, then you would do the vote calculation and ranking via some batch process that runs every 10-15 minutes.
Also at this level, you would start using an algorithm to weight the vote values. For example, if the same user votes (up or down) the same product more than once a day(or once every) then the votes after the first should not count towards calculating the rank of the product.
For Example, here is how Quora's Ranking Algorithm works
If the user is a "Power User" or has an account that is more active, maybe their vote is more important than a new users vote. I think on Yelp, if you don't have more than one or two reviews, your rating and reviews don't get counted until you meet some minimum number of reviews. Really, the skies the limit.
PS. I would also recommend checking out this o'Reilly book on some of the strategies for solving these kinds of problems
If you expect a large number of users simultaneously voting, you really need to consider performance....
A naive approach might look something like this (my apologies if i oversimplify your example, and if T-SQL isn't your poison):
create table Products(
ProductId BIGINT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
Score INT NOT NULL...
ProductDetails...
where you will be performing updates to Products by summing up/down vote tables. BAD!
If you have a large number of users voting, deadlocks are sure to occur by constantly inserting/updating/selecting against the same table.
A better approach would be to drop the Score column altogether, only insert into the up/down vote tables, and select as needed. There's no reason you can't calculate the sum in code (i.e. PHP, C#, or whatever), and it avoids ever having to update the Products table (at least for calculating the Score). In other words, storing the Score on the Products table buys you nothing, and is just unnecessary overhead.
I speak from experience when I say updates "can" be bad in high volume systems. Updating is expensive when compared to inserting at the end or selects (assuming your table is properly indexed), and it's very easy to unknowingly take out a substantial lock in situations like this.
Book Beginning CakePHP has an Ajax tutorial on implementing a working voting (up/down) system on comments. I did the tutorial a few years ago. I am not sure how secure it is or if it would be a good foundation for your project, but it would probably be worth having a look at for some ideas.