问题
I am trying to figure out best way to model class inheritance in DocumentDb. Say my classes are structured as
class A
property X
property Y
property Z
class B inherits from A
property W
Is there a built in support to hand this? If I use Lambda expressions in my client code, will it be able to distinguish b/w the types automatically?
Will following query only bring objects of type B back? Or will it also consider instances of base class A?
var bCollection = from o in client.CreateDocumentQuery<B>(collectionLink)
where X > 2
select o;
回答1:
Is there a built in support to hand this? If I use Lambda expressions in my client code, will it be able to distinguish b/w the types automatically?
Yes, you can use lambda syntax in client side, as long as you specify the specific type in the generic method, as client.CreateDocumentQuery<YourType>(collectionLink)
.
Will following query only bring objects of type B back? Or will it also consider instances of base class A?
DocumentDB is a schemaless store and does not store type information. The overloaded generic methods provided in the client are syntactic sugar, to let you easily create queries. All queries are evaluated against json documents, which do not have type information.
Inheritance scenario
So, if you fire a query for a property which is present only in your derived class, you will get values corresponding only to your derived class. But, if the property you are querying on is in both base class and derived class, you'll get back both results. For example, in your case filtering on W
would give you results of only class B
, but filtering on X, Y or Z
would give you values for both classes A
and B
.
Classes with shared schema in same collection
Note that this does not just happen in the base-derived class scenario. Same behavior would happen if you have 2 separate classes, which do not inherit each other, but have a property with the same name. Querying on that property will return results of both classes. For example, if you have 2 classes which are stored in the same collection:
class A1 { int x; }
class A2 { int x; }
Even if you form your query using the client.CreateDocumentQuery<A1>(collectionLink)
, results of both class A & B will be returned. As I mentioned earlier, the type specification in the client is just to make your life easier while forming the query.
I you want to be able to query different types of data, having shared schema elements, stored in the same collection - I would recommend having a separate property to store the type information manually and filtering on that property.
class DocumentDbData
{
string DataType;
DocumentDbData(string type) { DataType = type;}
}
class A1 : DocumentDbData
{
string x;
A1() : base("A1")
}
class A2 : DocumentDbData
{
string x;
A2() : base("A2")
}
The query, client.CreateDocumentQuery<A1>(collectionLink).Where(d => d.DataType == "A1" && d.x == "xvaluefilter")
will now return only data for class A1.
回答2:
I use node.js not .NET, so I don't recognize the CreateDocumentQuery<B>
syntax. Is there a way to inspect the actual query that is sent by the .NET SDK to see if there is something added to the WHERE clause to restrict the results to type B? Alternatively, is there some field like _Type
added to your documents without your intervention? I highly doubt the query clause you provided is so modified. I'm less sure that an _Type
field isn't added, but I consider it less than 50% likely. My instinct is just that the <B>
specification on the CreateDocumentQuery
simply casts the returned objects to type B for you. I have no idea if that will cause an error if your result set included class A objects or if it will use null or some other default for missing fields.
Assuming all of the above, you'll probably have to model class hierarchy yourself. I have modeled this in two different ways:
Use a materialized array to indicate the entire class hierarchy for each document. So, ["Animal", "Mammal", "Cat"]. Then when you want all Mammals, you can query with
WHERE "Mammal" IN c.class
.More recently, I've switched to having a separate field for each type that something is. So,
isAnimal = true
,isMammal = true
, andisCat = true
. This is more of a mixin approach, but you can still model class hierarchies this way.
来源:https://stackoverflow.com/questions/33059867/class-inheritance-in-documentdb