Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic collection NamingStrategy #2935

Open
agiannone opened this issue Mar 13, 2024 · 4 comments
Open

Dynamic collection NamingStrategy #2935

agiannone opened this issue Mar 13, 2024 · 4 comments

Comments

@agiannone
Copy link

Is your feature request related to a problem? Please describe.
We use different collections based on the tenant. Previously (v1.x) it was possible to override the getCollectionName method in the Mapper. We would like to be able to use a dynamic NamingStrategy based on the current tenant. However, the current NamingStrategy sets the collectionName in the EntityModel on load and it cannot be changed after that.

Describe the solution you'd like
The NamingStrategy should be called when the getCollectionName() method is called on the EntityModel. Or at least, there should be an option to make it dynamic, so that it's called on getCollectionName().

Describe alternatives you've considered
Can't see any alternative options at the moment.

@evanchooly
Copy link
Member

You can define your own NamingStrategy and configure Morphia to use that instead. Simply pass the class name for your custom strategy rather than the named type.

@agiannone
Copy link
Author

We have implemented the NamingStrategy but it's applied when the EntityModel is first mapped and cannot be changed after that.

In our case, we have multiple collections for the same object, one for each tenant. Which collection the object is written to depends on which tenant is currently saving the object. For example, we have tenanta.objects, tenantb.objects, tenantc.objects and so on.

The NamingStrategy allows us to manipulate the objects part of the collection name, but not to dynamically add the tenant part.

Before we used to override the getCollectionName method of the Mapper which was called when the collection name was needed. However, with the NamingStrategy that's no longer possible as it's set upfront.

@evanchooly
Copy link
Member

Multitenancy isn't directly supported in 2.x though it's on the roadmap for 3.x. If you need something like that now, your best bet is to create a Datastore per tenant which is less than ideal, I would agree, but as of now it's the only real option.

@agiannone
Copy link
Author

agiannone commented Mar 16, 2024

I've made the change locally to support this use case.

I've added a new method to the EntityModelBuilder which exposes the NamingStrategy. Then in the EntityModel constructor I store a copy of the NamingStrategy in the EntityModel itself. That way the NamingStrategy can be called directly when getCollectionName is called.

@NonNull
public String getCollectionName() {
    if (namingStrategy == null) {
       throw new MappingException(Sofia.noMappedCollection(getType().getName()));
    }
    return namingStrategy.apply(type.getSimpleName());
}

As NamingStrategy is called at runtime, we can use it to supply the tenant.

Not sure if this works as a broader solution, but thought it might be worth sharing. Of course, it could be optimised, maybe with an option specifying if the NamingStrategy should be cached, in which it works as it did previously.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants