Single multi-tenanted firestore or many single tenanted firestores? - firebase

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.

Related

Changing data model in existing cloud firestore collection?

Suppose I have a users collection. The users collection has a large number of documents in it. Now in my app, I have a feature request that forces me to add or remove a field in my users collection data model. How can I add a new field or remove an existing field from all my users documents? Is there any best practice that the community recommends here?
How can I add a new field or remove an existing field from all my users documents?
While #AdityaNandardhane solution might work, please note that if you have a lot of documents, then you have a lot of update operations to perform, which also means that you have to play a lot of writes.
So the best approach would be to perform the update, only when the user reads the document. When it comes to users, most likely the details of the users are displayed on a profile screen. This means that when the users want to check the profile, before displaying the data, check for the existence of the new field. If it doesn't exist, then perform the update operation, and right after that display the data, otherwise, just display the data. This means that you'll have to pay for an update operation only when needed. It doesn't make any sense to update all documents, of all users, since there may be users that will never use their accounts anymore. So there is no need to pay for them.
As I understood, You can do the following thing
1. Add New Field
If you are using Firebase Functions- you can create one function and write an update query with a new field and set one default value and Run the function. You can do the same from android also with kotlin/java.
2. Remove existing Field
If you are using Firebase Functions- you can create one function and write a query to delete one field and Run the function. You can do the same from android also with kotlin/java.
Look for a better approach If any, Its suggestion as per my knowledge.

Firestore data structure for two use cases

I would appreciate some guidance on how to structure data stored within an app. While there are some reasons for the first way, I'm concerned it wouldn't be able to operate efficiently for the second case.
Simplified, the app would contain a list of Places by State. The main use case would be viewing Places within a selected State. The second use case would be that individual users could save specific Places they liked into their profile and view them all at once (showing all state Places in one list).
Option 1- Places saved in one "places" collection, which has a field of "state."
Main use: To show these places by state, the app would query where the "state" field matches the state.
Secondary use: When a user saved the place, the app would save the docID for each place into the user's profile, each of which would need to be retrieved to show the list of places.
Option 2- Have one collection per state.
Main use: To show these places by state, the app would pull all documents within the query and list them out.
Secondary use: When a user saved the place to the user's profile, the app would save the docID for each place into the user's profile, distributed across the different collections, each of which would need to be retrieved to show the list of places.
Goals:
Use the same place document to appear in both the State lists and the user's profile.
Minimize the number of calls/slowness as much as possible in the Secondary use case.
I have been reviewing Firestore data storage guidelines, but I would appreciate any thoughts from experienced developers regarding this data structure.
There is no "perfect", "the best" or "the correct" solution for structuring a Firestore database. We are usually structuring the database according to the queries that we intend to perform.
Regarding storing all the places in a single collection vs. having one collection per state, please note that there is no difference in terms of speed or costs. You'll always have to pay a number of reads that is equal to the number of documents that your query returns. However, if you need to display in your app, for example, all places of all states, then having a collection for each state, will require a separate query for each state.
Furthermore, regarding saving a list of places in a user's profile vs. storing only the IDs, it's a matter of measurement. You should measure how often the details within the places are changed. Remember that if a place is changed, then you should update that data in all places it exists. So if it's not changed so often then you can save the entire place object, otherwise, save only the ID.

How can I allow the Current User to have permissions/views tied to their Direct Reports and Manager relationships?

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.

Dynamic querying of translated keywords

I'm trying to use the dynamic query api to determine if components are available in Tridion based upon a users audience manager profile.
One of these fields in their profile is 'Country' - which is recorded as free text in the extended details part of the audience manager profile, but based on a keyword from a 'Countries' category. We cannot store it as a keyword unfortunately due to client requirements.
It's expected that certain forms on the website being developed will be pre-filled using profile information from audience manager, for example pre-selecting a users country from a dropdown menu.
My concern is that if the 'Countries' category is translated in another publication, it would be impossible to pre-populate countries dropdown menus on forms because of the translated country names would be different.
Is that the case, or is it possible to translate and audience manager profile as well?
If you can get the local keyword (the Chinese one in your example). From there you can do a "Using Items" look up to find the Parent Keyword. I don't have the specific code, but if you check in the GUI, you can see the parent in the Used Items tab if you do a Where Used on the localised Keyword.
I don't know how specific this is to Audience manager. Isn't it more of a general blueprinting question? As you say, if you translate the country names keywords, the translated values are, of course, what will be published to the content delivery system. It may make sense to use the translated values in your site; otherwise why would you translate them?
If there are good reasons for wanting to use the untranslated values, then you can easily do this by publishing also from the parent publication, and writing your queries to operate in the context of that publication. As you have both values available, you can build your programme logic to make use of whichever one makes sense, and still have the benefit of a clear relationship between the two.

Assigning a specific (group of) reviewers in Plone (by 'hand' or automatically)

Is it possible to assign a person or a group of people as reviewers in a certain state of a workflow in Plone?
I have been looking at AutoRole en the IRolesplugin, but do not seem to find what I need?
In our case, users need a multiple review step workflow, yet the first reviewer should have control over which reviewers come afterwards...
Workflows can trigger scripts. Scripts can do things like grant roles to users. You'd have to come up with an approach to letting your first specify additional users. There are probably multiple ways to do it, but I could imagine using archetypes.schemextender or a custom content type to provide a field for choosing additional reviewers, only visible to initial reviewers. Then use those values in the workflow script. http://plone.org/documentation/kb/creating-workflows-in-plone/tutorial-all-pages provides a good overview of how DCWorkflow works.

Resources