Skip to content
New issue

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

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

Already on GitHub? # to your account

Add support for flexible document references #3602

Closed
christophstrobl opened this issue Mar 19, 2021 · 0 comments
Closed

Add support for flexible document references #3602

christophstrobl opened this issue Mar 19, 2021 · 0 comments
Assignees
Labels
type: enhancement A general enhancement

Comments

@christophstrobl
Copy link
Member

The goal is support linking documents without the need of using the fixed structure of a DBRef (related to: #2780).

Linking via Entity id

The @Id value of the referenced entity is used for linking.
The domain type serves as collection source on read.

class Order {
	
	@Id Long orderId;

	@ManualReference
	Customer customer;
}

class Customer {
	@Id Long customerId;
}
// write
{
	'_id' : 1,
	'customer' : 100,
}

// read
db.customer.find({ '_id' : 100 }).limit(1)

Linking via custom object

The reference value used for storing is provided via a DomainType -> ObjectReference converter.
The lookup attribute uses SpEL to create the filter query following the annotated query syntax from @Query. The target collection that can be either read from the source document, domain type or is a fixed value.

class CustomerReferenceConverter implements Converter<Customer, ObjectReference> {

	public ObjectReference convert(Customer source) {
		return new org.bson.Document("id", source.getId())
			.append("collection", "customers");
	}
}

class Order {
	
	@Id Long orderId;

	@ManualReference(lookup = "{ '_id' : '?#{id}' }", collection = "?#{collection}")
	Customer customer;
}
// write
{
	'_id' : 1,
	'customer' : {
		'id' : 100,
		'collection' : 'customers'
	}
}

// read
db.customers.find({ '_id' : 100 }).limit(1)

The lookup filter can contain any valid expression as long as it is resolvable against the stored reference.

Linking multiple entities

Linking a collection of entities follows the same conversion patterns as described above. The main difference is that the values are stored within an array.
The provided filter expression is created for every entry and concatenated via the $or operator.

class Customer {
	
	@Id Long customerId;

	@ManualReference(lookup = "{ '_id' : '?#{target}' }")
	List<Order> orders;
}
// write
{
	'_id' : 100,
	'orders' : [1,2,3,5,8]
}

// read
db.order.find({ '$or' : [ { '_id' : 1 }, { '_id' : 2 }, ...] })

Element order can be messed up when loading documents from the store this way. The original order must be restored by using the filter as a reference without having to fetch objects one by one.

Lazy Loading

References can be resolved lazily delaying resolution on first access.
In this case on read a proxy is generated holding the actual source value and the lookup filter.

class Order {
	
	@Id Long orderId;

	@ManualReference(lazy = true)
	Customer customer;
}

Object methods like (toString) on unresolved proxies shall not trigger resolution but be served from the available source value. On write, in case the Proxy never got resolved, the original source is written back to the collection without an attempt of resolving it.

@christophstrobl christophstrobl self-assigned this Mar 19, 2021
@christophstrobl christophstrobl added the type: enhancement A general enhancement label Mar 19, 2021
mp911de added a commit that referenced this issue May 21, 2021
Original pull request: #3647.
Closes #3602.
mp911de pushed a commit that referenced this issue May 21, 2021
…query.

Simplify usage by computing the pointer from the lookup.
Update the reference documentation, add JavaDoc and refine API.

Original pull request: #3647.
Closes #3602.
mp911de added a commit that referenced this issue May 21, 2021
Rename ReferenceReader to ReferenceLookupDelegate.
Rename LazyLoadingProxyGenerator to LazyLoadingProxyFactory.
Rename DefaultReferenceLoader to MongoDatabaseFactoryReferenceLoader.

Reduce scope of LookupFunction and move it to ReferenceLookupDelegate.

Extract some checks into methods to reflect the underlying concepts. Simplify code, convert variables to constants where possible.

Original pull request: #3647.
Closes #3602.
mp911de pushed a commit that referenced this issue May 21, 2021
Also allow direct usage of (at)Reference from data commons to define associations.

Original pull request: #3647.
Closes #3602.
mp911de added a commit that referenced this issue May 21, 2021
Reduce dependencies in tests by using NoOpDbRefResolver.
Add since tags.

Tweak documentation. Extract entity references into own documentation fragment.

Original pull request: #3647.
Closes #3602.
mp911de added a commit that referenced this issue May 21, 2021
@mp911de mp911de added this to the 3.3 M1 (2021.1.0) milestone May 21, 2021
@mp911de mp911de changed the title Add support for manual references. Add support for flexible document references May 21, 2021
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants