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

Map collection and fields for `$lookup`/`$graphLookup` aggregation stage against domain type

Open evilmilo opened this issue 2 years ago • 3 comments

Working on a legacy code base, we've got lots of code that builds up aggregations including lookups, so we want to lookup the collection name for a class.

We've got an implementation that I'm guessing was at some point copied from mongo, but doesn't seem up to date and digging through code can assume it was copied from BasicMongoPersistentEntity

	public BasicMongoPersistentEntity(TypeInformation<T> typeInformation) {

		super(typeInformation, MongoPersistentPropertyComparator.INSTANCE);

		Class<?> rawType = typeInformation.getType();
		String fallback = MongoCollectionUtils.getPreferredCollectionName(rawType);

		if (this.isAnnotationPresent(Document.class)) {
			Document document = this.getRequiredAnnotation(Document.class);

			this.collection = StringUtils.hasText(document.collection()) ? document.collection() : fallback;
			this.language = StringUtils.hasText(document.language()) ? document.language() : "";
			this.expression = detectExpression(document.collection());
			this.collation = document.collation();
			this.collationExpression = detectExpression(document.collation());
		} else {

			this.collection = fallback;
			this.language = "";
			this.expression = null;
			this.collation = null;
			this.collationExpression = null;
		}

Is there any reason this isn't exposed as a static method call so anyone can resolve class name to collection name consistently with how mongo does it?

evilmilo avatar Apr 28 '23 08:04 evilmilo

Can you elaborate at which points you need the collection name explicitly? Unless I overlook something (perfectly possible) all our APIs (aggregations included) usually – at least also – take a type parameter where they expose an explicit collection name.

odrotbohm avatar Apr 28 '23 11:04 odrotbohm

We want to know what the name that is actually going to be used is, even if it didn't have a type parameter. We are required by our company to use Java API, and no literals, so have to build up things like:

Aggregation.lookup(
	getCollectionName(Project.class),
	Dashboard.FIELD_NAME_PROJECT_ID, 
	FIELD_NAME_ID_WITH_UNDERSCORE,
	FIELD_NAME_PROJECT
);

evilmilo avatar Apr 28 '23 14:04 evilmilo

MongoOperations already exposes getCollectionName. However, extending the Aggregation API to accept a type parameter for the foreign collection would in my opinion be a nice enhancement to enable something like:

lookup()
  .from(User.class)
  .localField("id")
  .foreignField("firstname")
  .pipeline(...

Having the type present would also allow to map the foreignField against it to capture any potential @Field annotations that customize the target field name.

christophstrobl avatar Jun 09 '23 05:06 christophstrobl