Unique Key / Idempotency key migration - postgresql

I am using PostgreSQL and I need to migrate Idempotency/unique key from customer id to user id.
Customer id is one to many mapped to user id.
Currently the unique index is customer id + date string
Further going, I expect no more than one entry in DB per user per day, therefore the unique index will be user id + date string.
How do I handle such migration without downtime?

Related

Deciding primary key for DynamoDB

I have 3 fields to store in DynamoDB: identity-1, identity-2, score.
identity-1 and identity-2 are always unique in the table, i.e. no two entries can have same identity-1 or identity-2.
We want to allow entries to either have one of identity-1 or identity-2 or have both. Example:
identity-1
identity-2
score
a1
b1
s1
a2
s2
b3
s3
Access patterns are as follows:
Query identity-2 from identity-1
Query score from identity-1
Query score from identity-2
How do I define primary key in such case?
This is a "many:1" problem and there's a few ways to tackle it with DynamoDB. The simple answer here is to leverage Global Secondary Indexes (GSI). For every "identity" you wanted to do a direct look up from, you'd create a GSI.
GSI-1 would include Identity-1 as the hash key and you'd include Identity-2 and any other identities as a non-key attribute to include. You'd create a GSI for each identity you wanted to query directly on. You could also include the score as a non-key attribute if you wanted to directly look up score from any identity without having to resolve to the primary key (which we'll talk about).
The thing to consider with GSI's, though, is that they consume extra storage and throughput. If you create a GSI which includes all your attributes for every identity, you'd be paying for an additional copy of your table for each identity.
The other issue, so far, is that you haven't chosen a Primary Key for your table. You'll need a field to be your primary key and if none of your identities is non-nullable, you'll need a field which will be. It's often convenient to just call it what it is, so we'll call it pk.
You've got a few choices for pk here. Once is to define pk as a composite of your identities. For example: item.pk = item["identity-1"] || item["identity-2"]. Then you could do a query on the table for the identity == pk and if you don't find anything, you could then look up the index for the given identity. This works fine for your simple example, but as you wanted to do more complex things (such as many different identity types), you might find it to be a bit of a headache.
From past experience, my recommendation would be to adjust your approach slightly, however, and have an "users" table and a "scores" table. "users" would have a pk of a guid unique for every user and all their identities (call it "user_id"), you could then create a GSI for that table for every identity back to user_id. Then scores would then use "user_id" as the pk as well with no need for an index. Your application would always resolve to a "user_id" when a user was logged in or otherwise identified - then you can search for score without needing to track identity and you can look up all the associated identities or other user information without needing to create a very "fat" index of every identity->every other identity.

How to add non unique value into a unique list while still allowing value to be updatable

I have a simple database schema with User records
User
id - uuid pk
email - not null
List
id - uuid pk
List Entry
id - uuid pk
userId - uuid references User (id)
listId - uuid references ListEntry (id)
The trick is the system needs to guarantee uniqueness of User emails within a list while still allowing for the email of the User record to be updatable.
An obvious solution is the add email to the List Entry table with a unique index, but, this runs into issues with the requirement that the email is updatable. Especially because the application treats a User as its own standalone entity that can be modified in a place that does not know about Lists and ListEntries.
I do control the code executing updates and I have considered attempting a solution using serializable transactions to prevent duplicates, but, that seems worse than trying to keep the two email fields in sync.

Extend User authentication object in Azure Mobile Services

Is it possible to add additional properties to the User object on the server in WAMS? I would like to store the Id primary key of my User table for (secure) use in my table scripts. At the moment the only id is the vendor specific authentication Id, but I'd like to be able to allow users to choose an authentication method. Currently my (simplified) table design is as follows:
User table:
id
googleId
twitterId
facebookId
name, etc...
League table
id
userId
name, etc
I'd like to store the user primary key in the userId field on the league table, and then query it to ensure that users only get to see leagues they created. At the moment, the user object in table scripts sends through a User object with the Google/Twitter/Windows authentication token and I have to do a query to get the primary key userID, everytime I want to carry out an operation on a table with a userId column.
Ideal solution would be that when the Insert script on my User table is called on registrations and logins I can do:
// PSEUDO CODE
function insert(item, user, request) {
var appUserId;
Query the user table using the user.userId Google/Twitter/Facebook id
If user exists {
// Set a persisted appUserId to use in all subsequent table scripts.
user.appUserId = results.id;
} else {
Set the GooTwitFace columns on the user table, from user.userId
insert the user then get the inserted record id
// Set a persisted appUserId to use in all subsequent table scripts
user.appUserId = insertUserPK;
}
}
Then, in subsequent table scripts, I'd like to use user.appUserId in queries
If all you are trying to do is authorize users to only have access to their own data, I'm not sure you even need the "user" table. Just use the provider-specific userId on the user object to query your "league" table (making sure the userId column is indexed). The values will be provider-specific, but that shouldn't make any difference.
If you are trying to maintain a notion of a single user identity across the user's Google/Facebook/Twitter logins, that's a more complicated problem where you would need a "user" table and the kind of lookup you are describing. We hope to ship support for this scenario as a feature out of the box. It is possible (but fairly messy) to do this yourself, let me know if that's what you're trying to do.

Zend Framework Doctrine insert one-to-many

Amongst order tables i have a Customers table and Addresses table. A customer can have many addresses so I have setup a one-to-many relationship in a yaml file. The thing is the id for the Customers table is auto generated so I would not know the Customers_id until after the insert however, the Customers_id is a foreign key in the Addresses table.
The information for both tables is captured on the same form although each set of data is in a subform. How do I get Doctrine to insert the data into the Customers table then fetch the Customers_id just entered and use it as the foreign key for the Addresses table.
Hope I have been able to get the essence of the question across.
BTW I am using Zend Framework and Doctrine 1.2.3
Once you do $customer->save(), you may use $customer->id (if "id" is the Customers_id column name of your customer table) to get the Customers_id to put in Addresses table.
Once you do $customer->save(); the following statement $customer->identifier(); should give you the id.
Assuming you are using Doctrine 1.x you could do the following:
$cusomer->Address[] = $address; // Assign multiple addresses in this manner
$customer->save();
This will first save the customer details to the db and then store the address data. Since doctrine understands the relationship between customer and address, the ORM will insert the customer id in the address table. Further this will be run within a transaction by Doctrine which ensures that if one of the operations fail the entire transaction will be rolled back.

Query to database with 'primary key' on GoogleAppEngine?

I've made a guestbook application using Google App Engine(GAE):python and the client is running on iPhone.
It has ability to write messages on the board with nickname.
The entity has 3 fileds:
nickname
date
message
And I'm about to make another feature that user can post reply(or comment) on a message.
But to do this, I think there should a 'primary key' to the guestbook entity, so I can put some information about the reply on a message.
With that three fields, I can't get just one message out of database.
I'm a newbie to database. Does database save some kind of index automatically? or is it has to be done by user?
And if it's done automatically by database itself(or not), how can I get just one entity with the key??
And I want to get some advise about how to make reply feature generally also. Thanks to read.
Every entity has a key. If you don't assign a key_name when you create the entity, part of the key is an automatically-assigned numeric ID. Properties other than long text fields are automatically indexed unless you specify otherwise.
To get an entity if you know the key, you simply do db.get(key). For the replies, you probably want to use a db.ReferenceProperty in the reply entity to point to the parent message; this will automatically create a backreference query in the message to get replies.
Each entity has a key, it contains information such as the kind of entity it is, it's namespace, parent entities, and the most importantly a unique identifier (optionally user specifiable).
You can get the key of an entity using the key method that all entities have.
message.key()
A key can be converted to and from a URL-safe string.
message_key = str(message.key())
message = Message.get(message_key)
If the key has a user-specified unique identifier (key name), you can access it like this
message.key().name()
Alternatively, if a key name was not specified, an id will be automatically assigned.
message.key().id()
To assign a key name to an entity, you must specify it when creating the entity, you are not able to add/remove or change the key name afterwards.
message = Message(key_name='someusefulstring', content='etc')
message.put()
You will then be able to fetch the message from the datastore using the key name
message = Message.get_by_key_name('someusefulstring')
Use the db.ReferenceProperty to store a reference to another entity (can be of any kind)
It's a good idea to use key name whenever possible, as fetching from the datastore is much faster using them, as it doesn't involve querying.