Query MongoDB to find array that contains elements from another array - arrays

For my users table, each user has an emails<Array> property allowing them to associate multiple emails with their accounts. I want to make sure this is still unique so wether they're creating a new account or updating existing I need to query the DB to identify if that email address exists.
I know I can use users.find({ emails: email }) and could loop over that to identify, then check the _id (on update) to ensure everything but that puts me in a loop outside the query.
I'm curious if there's a method I'm not seeing for querying to identify if any emails being submitted match any emails from across the table in the db?

Related

Separating collections in mongodb database that share a 1-to-1 relationship

I am using mongodb as the database for a project I've been working on and in the database I have a "user" collection and an "account" collection. Every user has one account and every account has a "user" field that is the _id of the corresponding user. The reason I separated these into two collections is because I thought it made sense to keep the user's sensitive data (password, email, legal name, etc.) separate from the account data (things like interests, followers, username, etc.). Also the account collection has a lot of fields so it just seemed easier to not over-saturate the "user" collection with data.
So, my question is - Now that I essentially have 2 collections pointing to the same user, should I use the "user._id" to query both users and accounts? Since each account has a unique "user" field, is there a reason to query those accounts with their own _id property? It seems odd to keep track of two different _id's on the frontend and conditionally send either the user._id or account._id.
The two main drawbacks I have found when using the user._id to query both users and accounts is:
When querying account data, I have to almost always make sure I send the "user" field so I have that id on the front end.
If in the future, I wanted to add the ability for users to create multiple accounts, I would have to change the code to now fetch account data using the "account._id".
Hopefully that all makes sense, and maybe it doesn't even make sense for me to separate those collections. Thank you to anyone who can help!

Adding a Unique Index When Duplicate Values Exist in the Column

I have a problem with creating a unique existing field.
Standard Object - Account;
Field - EMail (several instances of the Account object with the same mail have already been created).
I want to make the field unique (do not repeat the values), how can I solve the problem with the existing data correctly? If through the method "point and click" to act, then an error is generated:
Error: Duplicate value (s) found when building unique index, example: blabla # gmail.com on rows
You'll have to delete the records (or maybe just clear the email fields on some?) before you can apply unique index. Salesforce has duplicate rules, you could use them to find matches, maybe the answer is to use merge operation, not delete? You can merge manually or with Apex. Or just run a report on Accounts grouped by email, sort by count descending and see what needs fixing.
If that bad data has to stay as is - best would be to configure duplicate rules to look at the field and prevent creating new? In this trailhead 2nd module has some screenshots that show how you can configure it to BLOCK inserts & updates. Not as good as true unique field but it's something...
Worst case you could cheat a bit. I mean depending on address if it's gmail then googlemail.com works, putting dots in the part before #... Won't work with all addresses though.

Change appengine ndb key

I have a game where I've (foolishly) made the db key equal to the users login email. I did this several years ago so I've got quite a few users now. Some users have asked to change their email login for my game. Is there a simple way to change the key? As far as I can tell I'd need to make a new entry with the new email and copy all the data across, then delete the old db entry. This is the user model but then I've got other models, like one for each game they are involved in, that store the user key so I'd have to loop though all of them as well and swap out for the new key.
Before I embark on this I wanted to see if anyone else had a better plan. There could be several models storing that old user key so I'm also worried about the process timing out.
It does keep it efficient to pull a db entry as I know the key from their email without doing a search, but it's pretty inflexible in hindsight
This is actually why you don't use a user's email as their key. Use ndb's default randomly generated key ids.
The efficiency you're referring is not having to query the user's email to retrieve the user id. But that only happens once on user login or from your admin screens when looking at someones account.
You should rip the bandade off now and do a schema-migration away from this model.
Create a new user model (i.e. UsersV2) and clone your existing user model into it to generate new ids.
On all models that reference it add a duplicate field user_v2 = ndb.KeyProperty(UsersV2) and populate it with the new key.
Delete the legacy user model
You should use the taskqueue to do something like this and then you won't have to worry about the process timing out:
https://cloud.google.com/appengine/articles/update_schema
Alternatively, if you are determined to do this cascading update everytime a user changes an email, you could set up a similar update_schema task for just that user.
I ended up adding a new property to my user model and running a crawler to copy the string key (the email) to that new property. I changed my code search for that property rather then the key string to get a user item. Most of my users still have keys that equal their email, but I can safely ignore them as if the string is meaningless. I can now change a users email easily without making a new recored and my other models that have pointers to these user keys can remain unchanged.

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.

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.

Resources