Expressing related documents as one object in RavenDB - ravendb

I'm just getting started with RavenDB and have studied the documentation about related documents. The system that I am thinking about working on has two classes, Family and Member.
A Family can have many Members and a Member can belong to many Families. Members can be retrieved individually as well and updated. From what I'm reading, the proper way to model this is to have a Document for Family and another document for Member. And to have Family contain a list of MemberIds.
Great!
The above approach is described on the RavenDB site at https://ravendb.net/docs/article-page/3.0/csharp/indexes/querying/handling-document-relationships
But, this means that you handle each of the object separately. You have to "fetch" each of the Member object individually by using a separate Load command. Even if you use an Include to "prefetch" all of the related objects into the session, you still have to issue a separate Load command for each one.
This means that the Family object doesn't contain a list of Member objects but only contains a list of MemberIds.
Here is my question: Is there a way to have RavenDB return a complex object from related documents so that when you get back a Family object, it will contain a list of the members objects that are related? I know that if you put the member objects directly in the family object, this can be done, but that will not allow a member object to be used elsewhere (other families).
Furthermore, is there a way to tell RavenDB to "deconstruct" certain embedded lists into related documents instead of storing it in the same document?
It seems like this would be a very helpful thing to have.

You can use a transformer for that, yes.

Related

What are the differences between Object Collections, Object Aggregates, Object Associations, and Object Composition?

I'm seeing these terms used and I'm thinking my own usage of them may be incorrect. I'm wondering exactly how they are different.
Object Collection - ???
Object Aggregation - ???
Object Association - ???
Object Composition - ???
It seems these terms come up lately when talking about ORMs, Data-mappers, and Repositories. For example, Fowler mentions object collections here. What do these terms mean specifically, and how should I use them effectively in speaking?
Object Collections
Is a more broader term, than "arrays", but, includes "arrays". Collections are objects by themselves, its main goal is to store several other objects, plus other features that depends on each collection kind, such the order of insertion, or order of extraction, if duplicated items are allowed, and so on.
Object Association
Is also, a very generic term, it implies there is a conceptual relationship between 2 objects. There are also, several kinds of "associations", with more specific goals.
Object Aggregation
Is an object association in which an object is related to another object. They can exist independently, and the creation or destruction of one, does not affect the other one, although some operations are result of the interaction of both objects.
Object Composition
Is an object association in which an object is part of another main object. The sub-object cannot exist independently, usually, it's creation or destruction, its managed by the main object.
Note:
Note: Object Aggregation and Object Composition are kinds of Object Association (s), but, there are not the only ones.
To add to umlcat's answer, with some examples:
(as mentioned here in this great post)
Example1: A Company is an aggregation of People. A Company is a composition of Accounts. When a Company ceases to do business its Accounts cease to exist but its People continue to exist.
Example 2: A Text Editor owns a Buffer (composition). A Text Editor uses a File (aggregation). When the Text Editor is closed, the Buffer is destroyed but the File itself is not destroyed.
Also, I would say it is worth noting that People could be moved to be strictly used inside Company (now composition) if you don't care about them ever existing independant of a Company. (Meaning that your application only allows for creation of people from inside a Company context. I don't think PHP lets you actually define classes within classes though. You'll ultimately just have to look at different areas of use in your application to determine if you are using composition or aggregation.)

Aliases for .net objects/methods, etc

One of our customers has requested changes to the names of dozens of the objects in our very large object hierarchy. This will definitely help them, as it maps our objects onto their real-world business object names.
Of course I don't want to change working code, so I'd prefer to use some sort of "alias" object for each of these renaming. I suspect that I can do this by declaring a second object with the alias'ed name, and then overriding any of the alias'ed methods…
But what happens when the object name doesn't change, only a method within it? This could get messy!
Anyone out there faced a similar problem or have any advice on how to attack this?

Should I make these methods non static

I am just practising Java OOPs concepts by building a dummy project of Library management system.
Initially I had classes for Book, Customer, Administrator (with Customer, Administrator extending abstract user class)
I then created list classes BookCollection, CustomerCollection which hold the list of instances of above classes in ArrayList (for a while am not dealing with databases) and perform add, delete, sort methods on corresponding ArrayList (just one inline question: will it be a good design practice if I replace ArrayList related code with database operation once I start dealing with database, with each xyzCollection dealing with xyzTable in database)
The main problem:
Since I thought earlier that I will have to maintain only list of books, customers across app, I made ArrayLists static. Also, I wrote enough of static methods: addXyz, deleteXyz, searchXyz, sortXyz methods However now I realize that for search of Customers or Books I may have (or rather should) to return list of them matching the name, that means I have to return another ArrayList, which should be an instance of xyzCollection, however I cant use ArrayList in these xyzCollection as it is staic shared among all instances.
Initially it was appearing I will need shared ArrayList, but am now doubting my initial decision.
What should be correct?:
Should I make ArrayList and corresponding methods non static and make any corresponding code changes at calls
Or should I return ArrayList instead of XyzCollection
What will be better in terms of code design? Or I have made definite mistake in making them all static?
I assume that you are creating collection books/customers after fetching data from DB. As you say its a library management system which means multiple users can use it simultaneously. And each request will be independent of other (like a typical distributed system).
So would suggest you to use normal class instead of static. You can use static for managing utilities like connection to db but not as placeholder like list of books/customers.
In my thinking working with database would be much easy then using the concept of array list. As by using array you have to make it shared so that values can be accessed. As I don't know your conceptual design of making it so consider it just an opinion.

How to model a relationship that NHibernate (or Hibernate) doesn’t easily support

I have a situation in which the ideal relationship, I believe, would involve Value Object Inheritance. This is unfortunately not supported in NHibernate so any solution I come up with will be less than perfect.
Let’s say that:
“Item” entities have a “Location” that can be in one of multiple different formats.
These formats are completely different with no overlapping fields.
We will deal with each Location in the format that is provided in the data with no attempt to convert from one format to another.
Each Item has exactly one Location.
“SpecialItem” is a subtype of Item, however, that is unique in that it has exactly two Locations.
“Group” entities aggregate Items.
“LocationGroup” is as subtype of Group.
LocationGroup also has a single Location that can be in any of the formats as described above.
Although I’m interested in Items by Group, I’m also interested in being able to find all items with the same Location, regardless of which group they are in.
I apologize for the number of stipulations listed above, but I’m afraid that simplifying it any further wouldn’t really reflect the difficulties of the situation. Here is how the above could be diagrammed:
Mapping Dilemma Diagram http://www.freeimagehosting.net/uploads/592ad48b1a.jpg
Analyzing the above, I make the following observations:
I treat Locations polymorphically, referring to the supertype rather than the subtype.
Logically, Locations should be “Value Objects” rather than entities since it is meaningless to differentiate between two Location objects that have all the same values. Thus equality between Locations should be based on field comparisons, not identifiers. Also, value objects should be immutable and shared references should not be allowed.
Using NHibernate (or Hibernate) one would typically map value objects using the “component” keyword which would cause the fields of the class to be mapped directly into the database table that represents the containing class. Put another way, there would not be a separate “Locations” table in the database (and Locations would therefore have no identifiers).
NHibernate (or Hibernate) do not currently support inheritance for value objects.
My choices as I see them are:
Ignore the fact that Locations should be value objects and map them as entities. This would take care of the inheritance mapping issues since NHibernate supports entity inheritance. The downside is that I then have to deal with aliasing issues. (Meaning that if multiple objects share a reference to the same Location, then changing values for one object’s Location would cause the location to change for other objects that share the reference to the same Location record.) I want to avoid this if possible. Another downside is that entities are typically compared by their IDs. This would mean that two Location objects would be considered not equal even if the values of all their fields are the same. This would be invalid and unacceptable from the business perspective.
Flatten Locations into a single class so that there are no longer inheritance relationships for Locations. This would allow Locations to be treated as value objects which could easily be handled by using “component” mapping in NHibernate. The downside in this case would be that the domain model becomes weaker, more fragile and less maintainable.
Do some “creative” mapping in the hbm files in order to force Location fields to be mapped into the containing entities’ tables without using the “component” keyword. This approach is described by Colin Jack here. My situation is more complicated than the one he describes due to the fact that SpecialItem has a second Location and the fact that a different entity, LocatedGroup, also has Locations. I could probably get it to work, but the mappings would be non-intuitive and therefore hard to understand and maintain by other developers in the future. Also, I suspect that these tricky mappings would likely not be possible using Fluent NHibernate so I would use the advantages of using that tool, at least in that situation.
Surely others out there have run into similar situations. I’m hoping someone who has “been there, done that” can share some wisdom. :-)
So here’s the question… Which approach should be preferred in this situation? Why? Is there a better option that I haven't considered?
Just a few observations / questions...
if the different location formats have no overlapping fields, what is the commonality in them which would make them candidates for a subclass hierarchy? Can you actually define a common interface for the base class Location?
is a TypeALocation comparable with a TypeBLocation?
are the two locations in SpecialItem of the same type, or can they be mixed?
can an item change its location to a different type runtime?
As you state above, value objects can't be polymorphic. Based on what you describe, I don't see how can you treat locations polymorphically.
Update If you can't define a common base interface for your location types, it is very awkward to try and treat them polymorphically, regardless of whether there is ORM or not. Taking your example below, even for accessing any information about the actual location I live, you needed to downcast it to either a street address or a lat/long coordinate. Polimorphism is meant exactly to avoid the need for such downcasts (and switches on type fields, etc.)!
Looking at the options you describe above, with all this taken into account:
Just as you, I don't like it either (hardly suprising).
Can be a viable option if there aren't many location types and you can be reasonably sure that you have implemented all the types ever needed. In this case the domain class would practically be the analog of a C union, with a type field. It is a bit awkward to use, but the polymorphic attempt would be even more awkward IMHO.
It is definitely an interesting idea which I will probably experiment with in a pet project sometime, but I am not quite sure I would like such tricks in my production code. I guess it could also be done with a custom mapping type which would map your component to a specific subclass. But then again, we're back trying to fit these incompatible types into a type hierarchy... the only good reason to try this path is if there are many location types and/or new types may appear in the future.

how to model value object relationships?

context:
I have an entity Book. A book can have one or more Descriptions. Descriptions are value objects.
problem:
A description can be more specific than another description. Eg if a description contains the content of the book and how the cover looks it is more specific than a description that only discusses how the cover looks. I don't know how to model this and how to have the repository save it. It is not the responsibility of the book nor of the book description to know these relationships. Some other object can handle this and then ask the repository to save the relationships. But BookRepository.addMoreSpecificDescription(Description, MoreSpecificDescription) seems difficult for the repository to save.
How is such a thing handled in DDD?
The other two answers are one direction (+1 btw). I am coming in after your edit to the original question, so here are my two cents...
I define a Value Object as an object with two or more properties that can (and is) shared amongst other entities. They can be shared only within a single Aggregate Root, that's fine too. Just the fact that they can (and are) shared.
To use your example, you define a "Description" as a Value Object. That tells me that "Description" with multiple properties can be shared amongst several Books. In the real-world, that does not make sense as we all know each book has unique descriptions written by the master of who authored or published the book. Hehe. So, I would argue that Descriptions aren't really Value Objects, but themselves are additional Entity objects within your Book Aggregate Root Entity boundery (you can have multiple entities within a single aggregate root's entity). Even books that are re-released, a newer revision, etc have slightly different descriptions describing that slight change.
I believe that answers your question - make the descriptions entity objects and protect them behind your main Book Entity Aggregate Root (e.g. Book.GetDescriptions()...). The rest of this answer addresses how I handle Value Objects in Repositories, for others reading this post...
For storing Value Objects in a repository, and retrieving them, we start to encroach onto the same territory I wrestled with myself when I went switched from a "Database-first" modeling approach to a DDD approach. I myself wreslted with this one, on how to store a Value Object in the DB, and retrieve it without an Identity. Until I stepped back and realized what i was doing...
In Domain Driven Design, you are modeling the Value Objects in your domain - not your data store. That is the key phrase. It means you are not designing the Value Objects to be stored as independant objects in the data store, you can store them however you like!
Let's take the common DDD example of Value Objects, that being an Address(). DDD presents that an Mailing Address is the perfect Value Object example, as the definition of a Value Object is an object of who's properties sum up to create the uniqueness of the object. If a property changes, it will be a different Value Object. And the same Value Object 9teh sum of its properties) can be shared amongst other Entities.
A Mailing Address is a location, a long/lat of a specific location on the planet. Multiple people can live at the address, and when someone moves, the new people to occupy the same Mailing Address now use the same Value Object.
So, I have a Person() object with a MailingAddress() object that has the address information in it. It is protected behind my Person() aggregate root with get/update/create methods/services.
Now, how do we store that and share it amongst the people in the same household? Ah, there lies DDD - you aren't modeling your data store straight from your DDD (even though, that would be nice). With that said, you simple create a single Table that presents your Person object, and it has the columns for your mailing address within it. It is the job of your Repository to re-hydrate that information back into your Person() and MailingAddress() object from the data store, and to split it up during the Create/Update operations.
Yep, you'd have duplicate data now in your data store. Three Person() entities with the same mailing address all now have three seperate copies of that Value Object data - and that is ok! Value Objects are meant to be copied and destoyed quite easily. "Copy" is the optimum word there in the DDD playbook.
So to sum up, Domain Drive Design is about modeling your Domain to represent your actual business use of the objects. You model a Person() entity and a MailingAddress Value Object seperately, as they are represented differently in your application. You persist them a copied-data, that being additional columns in the same table as your Person table.
All of the above is strict-DDD. But, DDD is meant to be just "suggestions", not rules to live by. That's why you are free to do what myself and many others have done, kind of a loose-DDD style. If you don't like the copied data, your only option is that being you can create a seperate table for MailingAddress() and stick an Identity column on it, and update your MailingAddress() object to have now have that identity on it - knowing you only use that identity to link it to other Person() objects that share it (I personally like a 3rd many-to-many relationship table, to keep the speed of the queries up). You would mask that Idenity (i.e. internal modifier) from being exposed outside of your Aggregate Root/Domain, so other layers (such as the Application or UI) do not know of the Identity column of the MailingAddress, if possible. Also, I would create a dedicated Repository just for MailingAddress, and use your PersonService layer to combine them into the correct object, Person.MailingAddress().
Sorry for the rant... :)
First, I think that reviews should be entities.
Second, why are you trying to model relationships between reviews? I don't see a natural relationship between them. "More specific than" is too vague to be useful as a relationship.
If you're having difficulty modeling the situation, that suggests that maybe there is no relationship.
I agree with Jason. I don't know what your rationale is for making reviews value objects.
I would expect a BookReview to have BookReviewContentItems so that you could have a method on the BookReview to call to decide if it is specific enough, where the method decides based on querying its collection of content items.