Backand deep querying - sql

I want to know if it is possible to retrieve and the collection of objects that an object holds in Backand.
For example - you have an object 'Trip' which has a one-to-many relationship with 'Destination' as a trip can have many destinations. The attribute 'destination' in object 'Trip' is a collection.
Is it possible, when querying for a 'Trip' object, that I am able to receive the associated 'Destination' objects that the 'Trip' object has a collection of ?

While getting the parent object (/1/objects/Trip) there is no way to get information on the collection object (Destination), so you need to create a query for it:
SELECT trip FROM Destination
WHERE trip IS NOT NULL
group by trip
The query will return all the Trip id(s), which you can loop and make a specific API request for each Trip. To get the collection of the Destinations use deep=true, like this:
/1/objects/Trip/1?deep=true
Depend on you client UI, you can do the code above and make it a Lazy load using Promise. You could create an on-demand action and run the loop on the server and return a JSON with all the data at once.

Related

When retrieving the list of "master" objects, Backand Fails to retrieve "slave" objects

When retrieving the list of "master" objects, Backand Fails to retrieve "slave" objects
app
springnutjs
When retrieving the list of "master" objects (the ones with the "collection, via" field),
Backand Fails to retrieve "slave" (the ones with the "object" field) objects
even if it does work retrieving the "master" objects when retrieving the list of all "slave" objects
In order to get collections ("slave") you need to use query parameter: deep=true. When calling a list of objects there is no deep at all, but when getting a single master with deep=true you will get all the children ("slaves").
For example, when you run /1/objects/master/1?deep=true you will get all slaves.
Running /1/objects/master?deep=true no slaved but only related objects.

Remove object from Active Record Relation without deleting it

I'm working in Ruby on Rails 4 with Postgresql, and I've hit a bit of a snag. We have an Active Record model called AttendanceRecord which belongs to an AttendanceDay, AttendanceSwipe, Course, and CourseTimeSlot. Attendance Records were supposed to be unique on these fields, but something went wrong and duplicates snuck in. So, I wrote a method to find all of the Attendance Records which were duplicated and only keep one of them.
In the course of that method, I built an Active Record Relation of objects that shared the same attributes, like so:
records = AttendanceRecord.where(course_id: attributes[0], course_time_slot_id: attributes[1], attendance_swipe_id: attributes[2], attendance_day_id: attributes[3])
Nice relation, right?
Next, I found the object that I wanted to keep and named it to_keep. Then, I tried to remove just that object from the relation, like this:
records.delete(to_keep)
Unfortunately, I discovered that the delete method works a little differently on a Relation than it does on an Array. Instead of simply removing the object from the list, it actually does delete it from the database (without the callbacks).
So: I'm wondering if there is a method that I'm missing that will remove my to_keep object from the Relation without actually touching the object itself. Then, I'll be able to safely call records.destroy_all and happily go about my business. :)
If you want to exclude an object from a relation you can do so by id. For example:
records.where('id <> ?', to_keep.id).destroy_all
or, thanks to #trushkevich, in rails 4 you can do:
records.where.not(id: to_keep.id).destroy_all
This means that destroy_all will be called on the records you've identified already but excluding the to_keep record.

Many-to-many relationships with NSFetchedResultsController

I have a model that looks like this:
and want to display it in a UITableView using an NSFetchedResultsController. I want to list all of the Objects for a given Owner, grouped by Group. For example, if we were to view the groups for some Owner Owner A the table view might look like this:
Group A
Object A
Object B
Object C
Group B
Object A
Object D
Group C
Group D
Object C
Object E
It's also important that the Groups be ordered by their name attribute (not shown in the schema above) and that NSFetchedResultsController delegate methods get called whenever Objects are modified or added/removed from a Group.
Given those requirements, I have set up the NSFetchedResultsController to fetch a bunch of Objects with a predicate like [NSPredicate predicateWithFormat:#"ANY groups.owner = %#", someOwner], which throws an NSInvalidArgumentException exception: "to-many key not allowed here". I have tried a few other predicates, but am stuck.
Any suggestions? Is this not something I should be using an NSFetchedResultsController for? Or is there a better way to model my data?
Thanks!
Edit: I actually got the predicate working with the above code, my mistake was in my sectionNameKeyPath argument. I was trying to pass in groups.name, which was what was producing the error. I can see why that way wouldn't work, but am struggling to find a different way to achieve the desired results. Perhaps a join object?
Edit 2: This works somewhat well with a join object like this:
There are two downsides that I see now. The first is that I have to enforce uniqueness myself using code. That's easy enough, but a bit of a nuisance. The second downside, that I don't yet see a way around, is that the NSFetchedResultsController will not call its delegate for updates to Objects anymore. I can live with that downside for now, but am happy to hear better suggestions.
I think the problem you're going to see is that if you have a fetched results controller searching for Objects then it's going to find each Object only exactly once. So each object will appear exactly once in your table. Whereas what you sort of want to do is invert things and find all the Groups, then displaying all the relevant contained Objects. In terms of the fetched results controller, rather than finding rows and thereby being able to divide into sections you want to find sections and thereby figure out what to supply as rows.
The easiest thing, I think, would be to create a fetched results controller on Group and to add an intermediary object of your own that remaps those to sections and supplies group.objects (with a suitably deterministic sorting applied) as the rows per section.
If you want the rows to be dynamic then I guess the easiest thing is to create a fetched results controller per section based on the feedback of the Group controller.
If that's all getting a bit painful and you want to just write your own collection logic then you'll probably want to catch NSManagedObjectContextDidSaveNotification and rerun your logic whenever that occurs. For memory efficiency reasons you probably want to keep hold only of the objectIDs and to get the appropriate objects only when the table view requests them via the existingObjectWithID:error: method on the context. Core Data has a built-in caching mechanism that responds appropriately to memory warnings so that's all written for you.
You shouldn't need a join object to get at data in Many to Many relationships
See this answer: How to deal with many to many relationships with NSFetchedResultsController?
And example project: https://github.com/dmathewwws/Many-to-Many-CoreData

WCF data services - Limiting related objects returned based on critera

I have an object graph consisting of a base employee object, and a set of related message objects.
I am able to return the employee objects based on search criteria on the employee properties (eg team) etc. However, if I expand on the messages, I get the full collection of messages back. I would like to be able to either take the top n messages (i.e. restrict to 10 most recent) or ideally use a date range on the message objects to limit how many are brought back.
So far I have not been able to figure out a way of doing this:
I get an error if I attempt to filter on properties on the message (&$filter=employee/message/StartDate gives an error ">No property 'StartDate' exists in type 'System.Data.Objects.DataClasses.EntityCollection`1).
Attempting to use Top on the message related object doesn't work either.
I have also tried using a WebGet extension that takes a string list of employee IDs. That works until the list gets too long, and then fails due to the URL getting too long (it might be possible to setup a paging mechanism on this approach)...
Unfortunately the UI control I am using requires the data to be in a fairly specific hierarchical shape, so I can't easily come at this from starting on the message side and working backwards.
Outside of making multiple calls does anyone know of a method to accomplish this with wcf data services?
Thanks!
M.
Looks like the only real way of doing this is in fact to reverse the direction of the query.
So instead of starting from the Employee, I go from the message side. You can filter back on the employee properties, and restrict on the Messages collection. Its not ideal, as it means iterating the collection on return to re-center it on the employee for what I am attempting to do, but it will work. The async nature of silverlight and rich client at least means while an extra iteration is required, it still appears to be reasonably fast.
Another interesting thing to note: the current version of odata/wcf data services does not support querying on properties of inherited classes, so I had to move the start/end date properties up to the base class in order to be able to restrict my search on them.
http://Site/Service.svc/Messages()?&$filter=Employee/OfficeName eq 'Toronto' and (year(StartDate) eq 2010 and month(StartDate) ge 9 )

NHibernate: If two calls are made to CreateCriteria, which list is Get<T> going to retrieve the object from?

Under one UnitOfWork (session) I may call CreateCriteria twice. My first call is to populate a grid for data editing. Let's say the data has been edited and flushed (saved) to the database and the grid is still open. After the data is edited, I may call CreateCriteria a second time to retrieve a list of objects that are validated and found in error.
Lets say ObjectA was retrieved by both calls to session.CreateCriteria. It was edited in the grid but found in error within the second list.
The first question would be: Considering first level cache, is ObjectA--that was retrieved from the second call to CreateCriteri--represent the one retrieved from the first call? or, better yet, did NHibernate "detect and reuse" ObjectA from the first call assuming the keys did not change?
To my final point in question: I want to edit ObjectA which was found in error, and let's say it was brought up in a ListBox. Therefore, I want to highlight that object, call session.Get()(key) in order to retrieve it from cache, then bring up a change form to change ObjectA's properties. Which object am I changing? The one from the first call to CreateCriteria or the second call? Are they the same?
Thank you in advance.
Second level cache
Take a look at http://ayende.com/Blog/archive/2006/07/24/DeepDivingIntoNHibernateTheSecondLevelCache.aspx and http://www.javalobby.org/java/forums/t48846.html
From the former:
The second level cache does not hold
entities, but collections of values
So, with caching setup properly, NHibernate will be able to recreate your object without having to get the actual values from the database. In other words, the object will be created the same as when it wasn't in cache, except that since the values are cached, NHibernate won't actually query the database since it already knows what's in there.
I'm not quite sure what you mean by "validation" and "found in error". Are you validating before insert? Typically my entities are validated before the insert/update and won't actually be inserted/updated if invalid.
Validation aside, what I think you're asking is that if you:
save something
do a flush
retrieve an item (from a new session) with the same key as the one saved in step 1
will you be retrieving the same reference to the object you saved in step 1(?). And the answer is no since NHibernate does not cache the OBJECT but rather the values so it can create a new entity populated with the cached values (instead of actually performing a DB query).
However, does that really matter? If you overload Equals such that equality of 2 entities are based on their ID, then finding the same (not reference equal, but same) item in a grid (or a hash of any kind) should be a snap.
First level cache
I didn't realize you were talking about 1st level cache. 1st level cache works as an identity map and does cache the instance of the object. Therefore, if you do 2 selects from the db based on the same ID, you will retrieve the same instance of the object.