spring-data-mongodb icon indicating copy to clipboard operation
spring-data-mongodb copied to clipboard

Support dynamic naming strategy for collection names [DATAMONGO-1863]

Open spring-projects-issues opened this issue 7 years ago • 9 comments

Dan Markhasin opened DATAMONGO-1863 and commented

As described in DATAMONGO-525 (https://jira.spring.io/browse/DATAMONGO-525), we are looking for a way to generate collection names dynamically to support multi-tenancy. This can be achieved by something as simple as a prefix or by a naming strategy mechanism, simliar to FieldNamingStrategy.

For example, the most simple solution that would work (for us) is to have something like this:

@Document(prefix = "${info.service_name}")
class Dog
{
private String breed;
}

That would generate a collection called animalService_Dog (assuming the service name is animalService). Any other solution is welcome, but I believe this is a major feature that is currently lacking which is critical for multi-tenancy support


Reference URL: https://jira.spring.io/browse/DATAMONGO-525

1 votes, 3 watchers

spring-projects-issues avatar Feb 05 '18 21:02 spring-projects-issues

Oliver Drotbohm commented

The collection attribute of @Document already supports SpEl expressions. Does that already do what you want?

spring-projects-issues avatar Feb 05 '18 22:02 spring-projects-issues

Dan Markhasin commented

I believe it does not - as per the example given in DATAMONGO-525, this needs to be dynamic with the ability to extract data from the annotated class itself. If there is any way to achieve my example (only provide a prefix and let BasicMongoPersistentEntity decide what the name of the collection should be given that prefix and the name of the annotated class), that would be great, but looking at the code I currently don't see any way of doing that. What I want to avoid is having to explicitly set the collection name on every class in my application, which is what I currently have to do, i.e.:

@Document(collection= "${info.service_name}_dog")
class Dog
{
private String breed;
}

@Document(collection= "${info.service_name}_cat")
class Cat
{
private String breed;
}

spring-projects-issues avatar Feb 06 '18 07:02 spring-projects-issues

Dan Markhasin commented

Any updates here? Do you need more information?

spring-projects-issues avatar Mar 27 '18 16:03 spring-projects-issues

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

spring-projects-issues avatar Jan 06 '21 15:01 spring-projects-issues

Does that already do what you want?

No, we need a way to specify in @Document annotation the collection name as property from properties file

alxalx22 avatar Apr 13 '21 07:04 alxalx22

https://www.examplefiles.net/cs/1040155

This link specifies how we can use dynamic collection names with the environment variables. It worked for me

harinibodipudi avatar Feb 09 '22 12:02 harinibodipudi

I am trying to do something like this, too. My use case entails a configuration that specifies a list of mongo urls, and/or a list of collections for the same URL. If, in my application, I want to perform a kind of query federation over some configured number of collections in one or more mongo instances, I need a way to set up the collection name in the repositories that I configure, especially if they use the same model class, and I don't want to mandate the exact name of the collection. Please let me know if that explanation doesn't make sense, and I will do my best to clear it up.

I can get halfway there, and I'll explain what that means. If I disable mongo repository auto-configuration, and create the repository myself, I can construct a MongoEntityInformation object, and pass the collection name as a constructor parameter. In a custom repo impl, I extend SimpleMongoRepository, and pass this (along with the mongo template) into the constructor. If I use methods from the SimpleMongoRepository base class, then it uses the collection name that is set in the MongoEntityInfo instance. But, if I have methods in the original interface (the one that you include the custom interface in the list of "implements") then it only uses the collection name derived from the model class (either the lower-camel-case version of the name, or whatever is in the @Document(collection = "<some-name-here>") annotation.

I have an example here that demonstrates what I mean. The test writes to embedded mongo, and you have to look in the log output to see the collection name. I don't have a test that checks for the collection that is used when interface methods are invoked, but I can add that soon. So, I think it may be a bug that SimpleMongoRepository obtains the collection name differently than repository interface methods. It is not a problem when there is no custom implementation. However, when there is a custom implementation, or when a developer forgoes auto-configuration for manual configuration in order to get more flexibility in a certain situation, then we get inconsistent behavior.

Steve973 avatar Nov 15 '22 17:11 Steve973

Does that already do what you want?

No, we need a way to specify in @Document annotation the collection name as property from properties file

This feature has already worked for quite a while. if you put @Document(collection = "#{@nameOfBeanHoldingSomeString}" on your model class, it will use the string value of a bean of that name as the collection name. In a configuration class, you read in some property, and expose it as a named bean. And that's it. My case, mentioned above, is a bit more complicated.

Steve973 avatar Nov 15 '22 17:11 Steve973

Related to: spring-projects/spring-data-commons#2369.

christophstrobl avatar Mar 23 '23 10:03 christophstrobl