Which database model to store data in? - database

I am writing an application in Google App Engine with python and I want to sort users and user posts into groups. Users will be able to tag a post with a group ID and then that post will be displayed on the group page.
I would also like to relate the users to the groups so that only members of a group can tag a post with that group ID and so that I can display all the users of a group on the side. I am wondering if it would be more efficient to have a property on the user which will have all of the groups listed (I am thinking max 10 or so) or would it be better to have a property on the Group model which lists all of the users (possibly a few hundred).
Is there much of a difference here?

Your data model should derive from the most likely use cases. What are you going to retrieve?
A. Show a list of groups to a user.
B. Show a list of users in a group.
Solution:
If only A, store unindexed list of groups in a property of a user entity.
If both, same as above but indexed.
If only B, store unindexed list of users in a property of a group entity.
NB: If you make a property indexed, you cannot put hundreds of user ids in it - it will lead to an exploding index.

Related

firebase firestore nosql design for chat app with groups

I am trying to think of a way to design the firestore db in a way that is efficient.
The main issue I am having with is how I should define "groups". Lets say a user is invited to a group chat and so the client needs to retrieve the data for that group chat, should I have a "groups" collection and then find the correct group document? OR, should I have a "groups" property in the user document that has a id to reference the group to retrieve?
In SQL, having a reference in a user's groups table would be the obvious answer, but I am not sure about firestore. I don't want to look through the entire collection of groups just to find the group that the user was newly invited in. Any tips? Also, my front end is in React and I am considering using the onSnapshot method to subscribe to the collection (that seems to be the best way to have real time updates).
What i believe is best for you is this :
First have a collection, suppose you make groups, and inside that every docuent has all the group unique ids,
And inside that for every group, i.e document, you can have a collection which holds all the chats for that group and group related info , like group type, etc etc
Hope it helps. feel free for doubts

How to prevent user to access other users' data?

PROBLEM
User authenticated into the application
Simple database schema: User ---> Document ---> Item
API to access to Document Items
If the logged user knows the id of items that belong to some other user, he can access to it.
I would like to prevent this behavior.
SOLUTION
The first solution I found is to add a userid field to every records in every table to check at every query if the record belong to the logged user.
This is a good solution? Do you know some better design pattern to prevent the user to access other users' data?
Thanks
If the documents belong to a user, adjust your queries so that only items that belong to the user's documents are retrieved. No need to add userIDs to the items themselves.
If you need to expose IDs to the users, make those IDs GUIDs, instead of consecutive numbers. While not a perfect solution, it makes it much harder to guess the IDs of other users' items,
If you're using Oracle, there's VPD, Virtual Private Database. You can use that to restrict access for users.

Creation of views based on roles in salesforce

If i assign two users to two roles,let's say CSM and sales rep. If I am the sales rep and I go to the campaigns tab and click on the Direct mail view to view records of type Direct mail,I will get a result set. Now if the CSM user tries to access the same view by clicking on the Direct mail view again he should be able to access a different set i.e different set of records of the type direct mail. How do I achieve this. This is of top priority in my task now.Thanks in advance!!
You could create two views with the same name then make them each visible to the appropriate set of users.
You need to create two Views, one that corresponds to each of the groups. For simplicity, you can name the Views the same thing so long as the Unique Name is, obviously, unique. I would recommend something like Direct_Mail_Sales and Direct_Mail_CSM for the unique names.
Set up the criteria for the views however you'd like.
When you get to the bottom of the configuration for each view, make sure to select "Visible to certain groups of users" and select the corresponding Role from the list. This will make sure that the view is only visible to the appropriate role.
Since The views have the same name, it will appear to the end user to be the same view.

Create multiselect lookup in salesforce using apex

I want to create a multi-select Contact Lookup.
What i want :
When user clicks on a lookup then he should be able to select multiple contacts from that.
What i have done:
I have created an object and a field inside that object using both
"Lookup" and
"MasterDetail Relationship" and
"Junction Object"
When i try to use this Field for any input text/Field then it always provides an option to select only one value from lookup but i want to have an option to select multiple.
Even in the Junction object i have created 2 master-detail relationships still lookup allows only one value to be selected.Moreover it makes the field mandatory which i don't want.
Links that i followed:
http://success.salesforce.com/questionDetail?qId=a1X30000000Hl5dEAC
https://ap1.salesforce.com/help/doc/user_ed.jsp?loc=help&section=help&hash=topic-title&target=relationships_manytomany.htm
Can anybody suggest me how to do this.
Its same as we use Email CC/BCC under Send Email option for any Lead.
Even you use a junction object a lookup is just that, it references (looks up to) one other record: when you create a record on the junction object you still have to set each lookup individually and you're still creating only one record.
Master Detail relationships are essentially lookups on steroids, one object becomes the child of the other and will be deleted if the parent object is deleted, they're not going to provide an interface to lookup to many records at once.
If you're not a developer then your best bet is to either just create on junction object record at a time, or look into using dataloader. You could prepare your data in Excel or similar and then upload all the records into Salesforce in one go.
If you are a developer, or have developers at your disposal, then what we've done in the past is create a Visualforce page to do the job. So if, for example, you wanted to link a bunch of contacts up to an Account, we'd have a single account lookup field on the page, then some search fields relating to fields on the contact. Using a SOQL query you can then find all contacts matching the search parameters and display them in a list, where you may want to provide checkboxes to allow the user to select the contacts they want. Then it's just a case of looping through the selected contacts, setting their Account field to be the chosen account.
There are areas in Salesforce (such as the send Email functionality you mentioned) where it's clear to see that bespoke work has been done to fulfil a specific task — another instance of what you want is in the area where you can manage campaign members. This is the model I've copied in the past when implementing a Visualforce page as described.
Good luck!
For adding multiple junction objects at one time, the only solution we have found is a custom Visualforce page, as described by LaceySnr.
For a slightly different problem, where we need to assign many of object B to object A, We have trained our users to do this with a view on object B. We are assigning Billing Accounts (B) to Payment Offices (A). The view on Billing Account has check boxes on the left side. The user checks the Billing Accounts to be assigned, then double-clicks on the Payment Office field on any of the checked rows. A pop-up asks if you want to update only the single row or all checked rows. By selecting 'all checked rows', the update is done to all of them.
The view is created by the user, who enters the selection criteria (name, address, state, etc.). All user-created views are visible only to them.

appengine data structure - child, parent or both?

I'm trying my hand at google appengine and using the datastore with php and quercus.
I'm not familiar with Java or Python, so lots of learning going on here. I've got pages rendering, and i'm able to get data in and out of the datastore.
The app I am building has users, groups, topics and comments.
A group has users, and users can belong to multiple groups.
When a user logs in, I display the groups they are members of, and the topics of those groups.
I've got this currently built in MySql, and am now figuring out how to get it into appengine.
The way I see it, a group is a parent which has topics and users as children. Topics have comments as children.
However, I have to get the groups that a user belongs to when the user logs in. Therefore, I was thinking of a separate parent entity which stores the user, contact and login info, and that user would have children containing the group id which each user belongs to, so that I know what groups to fetch.
The users are children of the group so that I can display all the users of a group, but maybe there is a more efficient way to do it.
Like this
Groups(EntityGroup) - GroupName, Owner
↳ Topics - TopicName, Content, Owner
↳ Comments - Comment, Owner
↳ Users - userid
Users(EntityGroup) - userName, email, password
↳ userGroup - groupid
Then, when a user logs in, the logic looks like this
SELECT groupid FROM Users where password=hashofpassword+uniqueusername
foreach(groupid as group){
SELECT users from group;
SELECT topics from group
foreach(topicid as topic){
SELECT comments;
}
}
The reason I'm looking at it like this is because when a user logs in, I can't very well go looking through each group for the user, and I only would want to store the login info in one place.
Please don't recommend me to the code.google.com documentation, as I've gone through that many times already, but am not completely understanding what's going on with appengine.
also, is the way I've outlined above the proper way to visualize the datastore? I think visualizing the data has been a struggle which might be causing some of the challenges.
It looks to me like there is a many-to-many relationship between Users and Groups, yes? A user can belong to many groups, and a Group can have many users who are subscribed to it. The most logical way to represent this is AppEngine to is to give the User entity a ListProperty that holds the Key of the eahc of the groups to which he belongs. In Python, it would look like this:
class User(db.Model):
userName = db.StringProperty()
email = db.EmailProperty()
password = db.StringProperty()
groups = ListProperty(db.Key)
Whenever the User subscribes to the group, you add the Group's key to the groups list.
Likewise, the Group entity will have a ListProperty that contains the Keys of each User who belongs to it.
You wouldn't want to make the Users children of the Group, as that would make it very difficult or impossible for a User to belong to more than one Group.
The difficulty that you will have is that when a User joins a group, you will need to update the Group in a Transaction -- you can only have one User being added to a Group at a time; otherwise, you have the possibility that one write will overwrite another. Presumably, the User can be updated outside of a transaction, as he or she should only be joining one group at a time.

Resources