I am making an MEAN stack app and use Mongoose alongside Mongo. I am struggling with organizing my objects in database. All works as expected but I have a feeling that the way I am doing things is wrong, but can't seem to find any resources on the topic that could help me, thus I hope somebody with some experience can share it with me.
I use Mongoose to create several schemas, and there is one dilemma I am facing, concerning nested objects in MongoDB.
Let's say I have a model that looks like that:
ParentSchema:{
property1:String,
children:[{}]
}
So, property1 is just some string, 'children' is an array that will contain objects of type 'Child' with some other properties, but also another array (f.ex. 'grandchildren:[{]} ), this time with another type of objects (Grandchild).
Child and Grandchild have no schemas and do not exist outside of the Parent, and will most likely be unique to each instance of Parent, so two Parents would not be sharing a Child object.
In my app, I am able to use urls such as '/parent/:id1/Child/:id2/Grandchild/:id3', where 'id1' is an actual id of Parent that Mongo generates, while 'id2' is an index of Child object instance stored in Parents array. The same goes for instances of Grandchildren stored inside Child object.
I was thinking that maybe having separate schemas for all 3 objects, and just saving references to objects is the way to go, like this:
ParentSchema:{
prop1:String,
children:[{type:ObjectId, ref:'Child'}]
}
ChildSchema:{
prop1:String,
granchildren:[{type : ObjectId, ref: 'Grandchild'}]
}
GrandChildSchema:{
prop1:String,
prop2:String
}
..but was unsure, as for me it implies that Child and GrandChild instances would be shared between different parents, however it seems easier to work with.
To sum up, I would like to know is:
which approach should I choose and why: first, second or maybe some other that I do not know about yet.
If I were to choose the second approach, should I create a separate API route for each of the objects?
How would I go about creating then? My wish is for the process to look like so:
Start creating Parent -> start creating first Child -> create some Grandchildren ->
finish creating Child -> start creating second Child -> ... -> finish creating Parent.
I apologize if the question is somehow weird, I will try to clarify as best as I can if required.
I would go with the second approach for a couple of reasons:
Schemas have better readability in my opinion.
They allow for data validation which you lack in the first approach.
Please note the answer below is primarily opinion based.
For the API design:
I think its really up to you as to which paths to expose to the consumer, since you've stated Child and Grandchild do not have the right to exist without a parent - I think your routes are fine as they are.
And finally - your process for creating these entities look fine to me. I would do the same thing myself.
Related
I am working on data migration project from production to developer sandbox and able to copy data of independent objects as well as parent child relationships using composite/tree rest api of salesforce.
I am stuck with one scenario as of now explained below:
NAP_News_Filter__c is an object having two lookups: NAP_Page_Builder__c and NAP_News_Item__c.
So as part of my understanding, NAP_Page_Builder__c and NAP_News_Item__c will become two individual parents and NAP_News_Filter__c will become child of both.
I am not able to understand how to handle such scenarios of two different jsons of different parent objects and both jsons will have same child. Because when second json will be passed, it will create duplicate record but what I want is child record having both parent lookups.
Can anyone who have knowledge on such scenarios help me out.
I'm working on a personal project using WPF with Entity Framework and Self Tracking Entities. I have a WCF web service which exposes some methods for the CRUD operations. Today I decided to do some tests and to see what actually travels over this service and even though I expected something like this, I got really disappointed. The problem is that for a simple update (or delete) operation for just one object - lets say Category I send to the server the whole object graph, including all of its parent categories, their items, child categories and their items, etc. I my case it was a 170 KB xml file on a really small database (2 main categories and about 20 total and about 60 items). I can't imagine what will happen if I have a really big database.
I tried to google for some articles concerning traffic optimization with STE, but with no success, so I decided to ask here if somebody has done something similar, knows some good practices, etc.
One of the possible ways I came out with is to get the data I need per object with more service calls:
return context.Categories.ToList();//only the categories
...
return context.Items.ToList();//only the items
Instead of:
return context.Categories.Include("Items").ToList();
This way the categories and the items will be separated and when making changes or deleting some objects the data sent over the wire will be less.
Has any of you faced a similar problem and how did you solve it or did you solve it?
We've encountered similiar challenges. First of all, as you already mentioned, is to keep the entities as small as possible (as dictated by the desired client functionality). And second, when sending entities back over the wire to be persisted: strip all navigation properties (nested objects) when they haven't changed. This sounds very simple but is not at all trivial. What we do is to recursively dig into the entities present in trackable collections of say the "topmost" entity (and their trackable collections, and theirs, and...) and remove them when their ChangeTracking state is "Unchanged". But be carefull with this, because in some cases you still need these entities because they have been removed or added to trackable collections of their parent entity (so then you shouldn't remove them).
This, what we call "StripEntity", is also mentioned (not with any code sample or whatsoever) in Julie Lerman's - Programming Entity Framework.
And although it might not be as efficient as a more purist kind of approach, the use of STE's saves a lot of code for queries against the database. We are not in need for optimal performance in a high traffic situation, so STE's suit our needs and takes away a lot of code to communicate with the database. You have to decide for your situation what the "best" solution is. Good luck!
You can find an Entity Framework project item at http://selftrackingentity.codeplex.com/. With version 0.9.8, I added a method called GetObjectGraphChanges() that returns an optimized entity object graph with only objects that have changes.
Also, there are two helper methods: EstimateObjectGraphSize() and EstimateObjectGraphChangeSize(). The first method returns the estimate size of the whole entity object along with its object graph; and the later returns the estimate size of the optimized entity object graph with only object that have changes. With these two helper methods, you can decide whether it makes sense to call GetObjectGraphChanges() or not.
I'm trying to find all object which have no parent (i.e. which were created with parent=None).
Using M.all().filter("parent = ", None).fetch(100) doesn't bring any results, even though some objects certainly do have no parent.
What am I doing wrong?
There's no way to query specifically for root entities. You need to either use external information (eg, no entity of type Foo has parents), or add a property that indicates if an entity is a root entity or not.
You don't use filter() to query for an ancestor. Try instead:
M.all().ancestor(None).fetch(100)
Edit: hmm, that won't work apparently (I'd swear I had done this somewhere). So you'd need to save an extra property as a flag for root entities.
Using parent child relationship where a parent can have children while each child has only one parent, does using Children.all().ancestor(parent.key) a good solution where a child is constructed by setting parent=parent.key in the constructor? Is the 1000 limit applies with this kind of query?
The query returns what you'd expect, all Children which have the specified parent anywhere in their ancestry. The query expresses exactly that, so I doubt there's a simpler way of doing the same thing. But App Engine does keep adding features and surprising me :-)
Possibly you need parent.key(), I think it depends whether you're in Python or Java.
Btw, it's not recommended to use ancestor-parent-child to model relationships in your data. Entity groups exist to enable transactions, not for use as a "free" ReferenceProperty. parent-child should be a low-level implementation detail, meaning either "these two entities may need to be modified in a single transaction", or perhaps "I am playing an optimization trick which allows me to use list properties without having to load the list into memory when I get the entity". As a rule of thumb, if the entities don't all "belong" to the same user, then they shouldn't be parent-child related, because relating them in that way introduces contention when different users try modify them via different datastore nodes:
http://code.google.com/appengine/docs/python/datastore/keysandentitygroups.html#Entity_Groups_Ancestors_and_Paths
Another way to get descendants (children) of a parent entity in Google App Engine that I just discovered:
childrenEntities = db.query_descendants(parentEntity).fetch(1000)
Not sure if it will be helpful to you. It was helpful to me because I was having difficulty figuring out how to access the child class(es) which were created with a python module I installed.
As others have indicated elsewhere, the 1000 limit for everything was removed in February 2010. See the linked blog entry for more details re: this.
I'm hoping someone's seen this. I've found no clues on Google.
I'm using Google AppEngine with JDO to persist my objects.
I have two objects, Parent and Child. Each Parent has n Child objects.
I initially stored the Child objects in an ArrayList data member in the Parent class.
I got the exception "java.lang.UnsupportedOperationException: FK Arrays not supported" when persisting the Parent object.
I put this down to my storing more than one Child key references, so changed it around so that the Child objects store key references to the Parent object instead. In this way, there is only one key reference per Child object instead of n key references per Parent object.
Yet the exception still gets thrown when persisting the Parent object. So I suspect I was mistaken about the probable cause of this exception.
Has anyone seen this exception or know what it means?
According to DataNucleus a lot of things are persisted by default... and they even had a complaint in their blog about the manual in the google app engine site, which said that you need to explicitly mark fields as #Persistent.
I figured out what was wrong.
It wasn't complaining about my ArrayList.
My Parent class had an array data member that I hadn't put an annotation on. Arrays are persisted by default in the absence of annotations.
I added the annotation #NotPersistent and this solved my problem.