Here are few things that I want to do with my data:
Add data without necessarily creating a user related to it. (as a node, maybe)
Create users related to that data, whenever needed.
Enable users to edit data related to them only without affecting anything else.
Make data easily searchable and filterable.
So what's the best approach? Do I create MANY users and add field to them with data, or create nodes?
And yes I am a beginner in Drupal.
Your question is very vague, but here is some general advice.
Only create Users if they really are USERS. Don't use the user entity to store general data, unless those data fields pertain to the user.
For example, if you need to store the mailing address of a user, add that field to the user object.
Related
I'm building a SaaS system that allows users to define their own data models and enter data according to those models. It's a bit like airtable.
One user might model a bookshop, and would have a Book model, with title and ISBN fields. Another user might model medical records, and would have "date of last visit" as a field.
In the case of the bookshop, I want users to be able to search on title and ISBN. In the case of the medical records, I want users to be able to search on the date of the last visit.
I am using Firestore as my backend.
Firestore requires an index to enable a search. So that approach will not scale as # of customers increases.
My thought therefore was to have a Firestore instance for each customer, and those specific instances would have the necessary indexes.
I'm sure there are downsides to doing this though.
What would folks recommend to best solve this need?
What you are trying to achieve is some kind of weird, since you will not provide at least a few standard common properties for each user of your Bookshop.
When you want to perform a search in a Cloud Firestore database, you need the exact name of the property on which you want to search for. Having dynamic properties might not help you solve the search feature. However, you can create a document with a property of type array that can hold the name of all properties the users have chosen and perform a search on every property, but this solution will be much too expensive.
In my opinion, a possible solution might be to create at least a few common properties, so you can have the properties on which you can search. When someone creates, for example, a book shop you can display at the beginning all available properties a user can choose. Once you create a shop, you can have different users with different shop properties. This means that if a user does not choose a property, when you perform a search on that property, the results won't contain his/her products. This will work, only if you have predefined properties.
In a handful of circumstances, I'd like to allow the Current User to be able view a list of records filtered by Owners of each record that are Direct Reports that they manage or even by the Manager they report to via our global directory.
I'm comfortable making a new Datasource for CurrentUser in a Directory model. However, I'm tripping over myself trying to find the best way to match an Ownership (email) field from a record, with an array of the direct reports associated with the current user.
A specific example would be on the Travel Approval template. The table on the Dashboard page has a filter for "My Requests | All" and I'd love to add a third option for "Direct Report Requests".
My assumption is that I would adjust the onClick event to filter results accordingly:
widget.datasource.query.pageIndex = 1;
widget.datasource.query.filters.Owner._equals = app.user.email;
widget.datasource.query.filters.Owner._in = null;
widget.datasource.load();
updateUrlForDashboard();
That's one small example, but more importantly, I'd like to get a better understanding of how best to reference/store those additional relationships about the Current User.
Ideally, a current user is able to have greater ability to manage (approve/deny/comment on) resources tied to their Direct Reports and generate records that provide a similar level of control to the Users that Manage them.
I'm not sure if that's best handle by some use of Roles or another approach. Any advice on how best to plan out that kind of setup would be much appreciated.
funny thing ... I had the same question a couple of months ago. I think you will find Pavel's solution on this very interesting. You can find it here.
If I have User and Profile objects. What is the best way to structure my collections in firestore given that the follow scenarios can take place?
Users have a single Profile
Users can update their Profile
Users can save other users' profiles
Users can deleted their saved profiles
The same profile can't be saved twice
If Users and Profiles are separate collections, what is the best way to store saved profiles?
One way that came to mind was that each user has a sub collection called SavedProfiles. The id of each document is the id of the profile. Each saved Profile only contains a reference to the user who's profile it belongs to.
The other option was to do the same thing but store the whole profile of each saved profile.
The benefits of the first approach is that when a user updates their own profile there's no need to update any of the their profiles that have already been saved as it's only the reference that is stored. However, attempting to read a user's saved profiles may require two read operations (which will be quite often), one to get all the references then querying for all the profiles with those reference (if that's even possible???). This seems quite expensive.
The second approach seems like the right way to go as it solves the problem of reading all the saved profiles. But updating multiple saved profiles seems like an issue as each user's saved profiles may be unique. I understand that it's possible to do a batch update but will it be necessary to query each user in the db for their saved profiles and check if that updated profile exists, if so update it? I'm not too sure which way to go. I'm not super used to NoSQL data structures and it already seems like I've done something wrong since I've used a sub collection since it's advised to keep everything as denormalized as possible so please let me know if the structure to my whole db is wrong too, which is also quite possible...
Please provide some examples of how to get and update profiles/saved profiles.
Thank you.
Welcome to the conundrum that is designing a NoSQL database. There is no right or wrong answer, here. It's whatever works best for you.
As you have identified, querying will be much easier with your second option. You can easily create a Cloud Function which updates any profiles which have been modified.
Your first option will require multiple gets to the database. It really depends how you plan to scale this and how quick you want your app to run.
Option 1 will be a slow user experience, while all of the data is fetched. Option 2 will be a much faster user experience, but will requre your Cloud Function to update every saved profile. However, this is a background task so wouldn't matter if it takes a few seconds.
I have a Plone 4 site which contains a lot of users and groups which are stored in the ZODB. Over time, we added some functionality which uses relational data (in a PostgreSQL database); some tables have fields which contain user or group ids.
However, currently the users and groups are defined in ZODB rather than the RDB, so we don't have proper foreign keys here. Thus, the obvious idea is to migrate the user and groups data to the RDB - those who/which are used by the Plone site, at least; I assume emergency users need to be an exception to this (but those are no members of any groups anyway).
Would this be a good thing to do?
Are there reasons to do it only partly, or should I transfer everything including group memberships? (Since memberships are stored as lists of users (and/or groups) with the containing group, I could imagine a reverse table which holds all groups a user is member of, and which is maintained by a trigger function.)
Are there any special tools to use?
Thank you!
imho it's based on what you want to achieve. In Plone you have PAS, so technically it doesn't really matter, where you put users, groups and user group relationships.
You can store users/groups in:
Plone (by default)
SQL - pas.plugins.sqlalchemy
LDAP/AD - Products.PloneLDAP
There are also many other plugins for AUTH, like RPX, Goolge+, etc.
You can enable, disable and modify the behabvior of every plugin thru PAS.
Does it make sense, to NOT use Plone users?
Of course, if you want to share user credentials (Example LDAP), or if you need the user informations in other Apps, etc.
Migration
Should be very simple if the PAS plugins you are using supports "Properties" and "User enumeration".
Get the data from one plugin and put the data into another one with a simple python script. Both supports the same API.
the tool you're looking for is https://pypi.python.org/pypi/pas.plugins.sqlalchemy/0.3
I've used this in a webportal where users are "shared" with a newsletter system.
I've 200 users and any problem.
I think the only "good reason" to store users in an external DB rather in zodb/plone is in a use-case like mine.
Have you ever think about "extend" plone users (ex. https://plone.org/products/collective.examples.userdata)? With plone.api you can easly manipulate users' properties in your code.
I hope you guys could help me come up with a new solution for a customer. The scope of the project detailed getting data from me. So I created a user interface where the user could select the data they wanted and I would create an xml file that automatically sent it to the user through email. I limited the user to only be able to select 5 items at a time so that the tool would not time out b/c there is a lot of data in the xml that needs to be generated based on the selection. Now the user is asking not to be limited to 5 and wants to be able to select how many he/she desires. My question is are there any other solutions to handle this problem.
one little hack to reuse your current solution would be to write a wrapper so as to accept any number of items as selection, then process them by chunks of 5 ( or whichever limit you choose)