SQL Statement to Single Entity Core Data Fetch Request - mysql

I have a single Entity in CoreData mimicking a MySQL database table with the following structure:
Photo
abv Double
photoId Integer16
photographer String
isActive Boolean
lastUpdated Data
name String
I can run the following SQL statement to get my desired result set:
SELECT `photographerName`, COUNT(`photographerName`)
FROM `Photos`
WHERE `isActive` LIKE 1
GROUP BY `photographerName`
ORDER BY `photographerName`
What combination of NSFetchRequest, NSSortDescriptor, NSPredicate, NSExpressionDescription can I use to achieve the same results in iOS?
I am using the following:
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Photo"];
NSSortDescriptor *photographerSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"photographer" ascending:YES selector:#selector(localizedCaseInsensitiveCompare:)];
NSPredicate *onlyActivePhotos = [NSPredicate predicateWithFormat:#"isActive == 1"];
request.sortDescriptors = #[photographerSortDescriptor];
request.predicate = onlyActivePhotos;
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
Which gets me the isActive fine, but returns a row for every Photo, not Photographer.
Or... should I be splitting this into two Entities? For example, Photographer with a one-to-many relationship to Photos?

First, it is certainly better and more flexible design to have a relationship Photo-Photographer.
However, what you want can also be achieved. You can only get the photo entities, so after you have to filter the resulting array to just return your photographer names.
NSArray *photographerNames = [fetchedResultsController.fetchedObjects
valueForKeyPath:"#photographer"];
NSSet *uniqueNames = [NSSet setWithArray:photographerNames];
NSArray *orderedNames = [uniqueNames sortedArrayUsingDescriptors:
#[[NSSortDescriptor sortDescriptorWithKey:#"self" ascending:YES]]];
As you can see, this is quite cumbersome. Also, you have lost the information which photos are associated with each photographer.
So please go with the relationship. After all, Core Data is an object graph, not a database wrapper.

Related

Getting all unique/distinct elements from a many to many field django

Say that I have this structure:
class Distinct_Alert(models.Model):
entities = models.ManyToManyField(to='Entity', through='Entity_To_Alert_Map')
objects = Distinct_Alert_Manager()
has_unattended = models.BooleanField(default=True)
latest_alert_datetime = models.DateTimeField(null=True)
class Entity_To_Alert_Map(models.Model):
entity = models.ForeignKey(Entity, on_delete=models.CASCADE)
distinct_alert = models.ForeignKey(Distinct_Alert, on_delete=models.CASCADE)
entity_alert_relationship_label = models.TextField()
class Entity(models.Model):
label = models.CharField(max_length=700, blank=False)
related_entities = models.ManyToManyField('self')
identical_entities = models.ManyToManyField('self')
objects = Entity_Manager()
disregarding the other fields, what I'm trying to do is get all the unique entities from a selection of distinct alerts. So say that I pull 3 distinct alerts, and each of them have 4 entities in its manytomany entity field, say that across them, a couple are shared, I want to get only the distinct ones.
I'm doing this:
ret_list = map(lambda x: x.get_dictionary(), itertools.chain(*[alert.entities.all() for alert in
Distinct_Alert.objects.filter(
has_unattended=True,
entities__related_entities__label=threat_group_label)]))
return [dict(t) for t in set([tuple(d.items()) for d in ret_list])]
But as I imagine, this isn't optimal at all since I end up pulling a lot of dupes and then deduping at the end. I've tried pulling the distinct value entities but that pulls me a Long that's used as a key to map the entities to the distinct alert table. Any way to improve this?
Can you try this?
entity_ids = EntityToAlertMap.objects.filter(distinct_alert__has_unattended=True,
entity__related_entities__label=thread_group_label)) \
.values_list('entity', flat=True).distinct()
Entity.objects.filter(id__in=entity_ids)
Django doc about values_list.

filling a select field with model with certain tag - laravel

I have no problem with selecting a model tagged with certain tag
$lis = Capacitytype::find(124)->entities()->orderBy('name','asc')->get();
In my Capacitytype model I have this relation:
public function entities()
{
return $this->belongsToMany('App\Models\Entity', 'entity_capacitytypes', 'capacitytype_id', 'entity_id');
}
MY PROBLEM:
I wish to use the same selection f models to fill a select field in a form. (I use select2.js)
When I try to implement this code
$lis = array(null => 'Commitee') + Capacitytype::find(124)->entities()->orderBy('name','asc')->lists('name', 'id')->all();
I get this error:
SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'id' in field list is ambiguous (SQL: select name, id from entities inner join entity_capacitytypes on entities.id = entity_capacitytypes.entity_id where entities.deleted_at is null and entity_capacitytypes.capacitytype_id = 6 order by name asc)
I tried to solve this issue by adding table name to my code, but this is as far as I was able to go:
->lists('entities.name', 'entities.id')
My Question:
how modify the code to get the desired collection for my select field?
Thank you.
You could make use of Laravel's with() to perform an eager loading as a workaround for this issue. To do so, just pass the name of the relation (i.e. entities) to the method:
Capacitytype::find(124)->with('entities')->orderBy('name','asc')->lists('entities.name', 'entities.id');
Or else, you could first fetch the records, and then reformat it to match your usecase:
$list = Capacitytype::find(124)->entities()->orderBy('name','asc')->get()->toArray();
As such, you can refine the returned list of arrays, to match your id => name format (hence, a substitute for the lists method).
$refinedList = array();
foreach($list as $entity){
$refinedList[$entity['id']] = $entity['name'];
}
And, there you go.

executequery in Grails doesn't load key : value json

I m doing something like this to get the data...
def prods = Product.executeQuery("select category.id,category.name, avg(competition1Price), avg(competition2Price), avg(onlineCompetitionPrice) from Product group by category.id")
render prods as JSON
Not the output I'm getting is this..
[[1,"Colchones y",1657.4784,2071.5,1242.5]]
these are just the values..
I want to use the same query and get key value pair..
like the way you do using findAll(query)
But I can't seem to implement this query using findAll()
Please Help
Thanks..
That's because the instances of prods are just objects with the result of your query and not instances of Product or other domain class (you used HQL that not represents a domain class). You can:
consider using a view for this query and mapping as a domain class;
manually build the output;
The second option is something like (not tested):
def output = [[:]]
prods.each { result ->
def prod = ['category.id' : result[0] , 'category.name': result[1]] //and so on...
output << prod
}
render output as JSON
Using this second option, to change the result produced, just cange the structure of your map. You can also have a list of maps if needed.

N-Tiered LinqToSql Question

I am hoping you can help. I am developing a tiered website using Linq to Sql. I created a new class(or object) in DBML designer called memberState. This object is not an actual table in the database. I have this method in my middle layer:
public override IEnumerable(memberState) GetMembersByState(string #state)
{
using (BulletinWizardDataContext context = DataContext)
{
IEnumerable(memberState) mems = (from m in context.Members
join ma in context.MemberAddresses
on m.UserId equals ma.UserId
join s in context.States
on ma.StateId equals s.StateId
where s.StateName == #state
select new memberState
{
userId = m.UserID,
firstName = m.FirstName,
middleInitial = m.MiddleInitial,
lastName = m.LastName,
createDate = m.CreateDate,
modifyDate = m.ModifyDate
}).ToArray(memberState)();
return mems;
}
}
The tables in my joins (Members, States, and MemberAddresses are actual tables in my Database). I created the object memberStates so I could use it in the query above (notice the Select New memberState. When the data is updated on the web page how do I persist the changes back to the Member Table? My Member Table consists of the following columns: UserId, FirstName, MiddleInitial, LastName, CreateDate, ModifyDate. I am not sure how save the changes back to the database.
Thanks,
If I remember correctly, you can create a view from the different tables (Members, States, and MemberAddresses) and add that to the data context. Then any modifications to data in the view object can be saved, and linq to sql will handle the commit correctly as long as all the relationships are clearly setup/defined in both the database and in the data context.
If you have a Member table, the dbml will most likely contain a Member class. To update a member in the database, you will have to create a new Member object, and the Attach it to the BulletinWizardDataContext.Members collection. Something similar to the following code should the trick (I have not tested the code):
using (BulletinWizardDataContext context = DataContext)
{
Member m = new Member() { UserId = userId };
context.Members.Attach(m);
m.FirstName = firstName;
// Set other properties
context.SubmitChanges();
}
Attach must be called before setting the properties. Also, Linq2Sql has some issues with Attach in the case where the properties of your object are set to default values (i.e. 0 for numeric values, false for booleans, null for string etc.). In this case Attach will not generate the correct SQL.
var m = myContext.Members.Single(m=> m.UserID == myMemState.userID);
m.FirstName = myMemState.firstName;
m.MiddleInitial = myMemState.middleInitial;
...
That would be the quick way. It does an additional roundtrip to the db, but will work well. If that's an issue for you, then do Attach like Jakob suggested. For that you have to have to do some extra steps, like reviewing the configuration for optimistic updates and make sure you have the original fields when doing the attach.

Linq to SQL Stored Procedures with Multiple Results

We have followed the approach below to get the data from multiple results using LINQ To SQL
CREATE PROCEDURE dbo.GetPostByID
(
#PostID int
)
AS
SELECT *
FROM Posts AS p
WHERE p.PostID = #PostID
SELECT c.*
FROM Categories AS c
JOIN PostCategories AS pc
ON (pc.CategoryID = c.CategoryID)
WHERE pc.PostID = #PostID
The calling method in the class the inherits from DataContext should look like:
[Database(Name = "Blog")]
public class BlogContext : DataContext
{
...
[Function(Name = "dbo.GetPostByID")]
[ResultType(typeof(Post))]
[ResultType(typeof(Category))]
public IMultipleResults GetPostByID(int postID)
{
IExecuteResult result =
this.ExecuteMethodCall(this,
((MethodInfo)(MethodInfo.GetCurrentMethod())),
postID);
return (IMultipleResults)(result.ReturnValue);
}
}
Notice that the method is decorated not only with the Function attribute that maps to the stored procedure name, but also with the ReturnType attributes with the types of the result sets that the stored procedure returns. Additionally, the method returns an untyped interface of IMultipleResults:
public interface IMultipleResults : IFunctionResult, IDisposable
{
IEnumerable<TElement> GetResult<TElement>();
}
so the program can use this interface in order to retrieve the results:
BlogContext ctx = new BlogContext(...);
IMultipleResults results = ctx.GetPostByID(...);
IEnumerable<Post> posts = results.GetResult<Post>();
IEnumerable<Category> categories = results.GetResult<Category>();
In the above stored procedures we had two select queries
1. Select query without join
2. Select query with Join
But in the above second select query the data which is displayed is from one of the table i.e. from Categories table. But we have used join and want to display the data table with the results from both the tables i.e. from Categories as well as PostCategories.
Please if anybody can let me know how to achieve this using LINQ to SQL
What is the performance trade-off if we use the above approach vis-à-vis implement the above approach with simple SQL
Scott Guthrie (the guy who runs the .Net dev teams at MS) covered how to do this on his blog some months ago much better than I ever could, link here. On that page there is a section titled "Handling Multiple Result Shapes from SPROCs". That explains how to handle multiple results from stored procs of different shapes (or the same shape).
I highly recommend subscribing to his RSS feed. He is pretty much THE authoritative source on all things .Net.
Heya dude - does this work?
IEnumerable<Post> posts;
IEnumerable<Category> categories;
using (BlogContext ctx = new BlogContext(...))
{
ctx.DeferredLoadingEnabled = false; // THIS IS IMPORTANT.
IMultipleResults results = ctx.GetPostByID(...);
posts = results.GetResult<Post>().ToList();
categories = results.GetResult<Category>().ToList();
}
// Now we need to associate each category to the post.
// ASSUMPTION: Each post has only one category (1-1 mapping).
if (posts != null)
{
foreach(var post in posts)
{
int postId = post.PostId;
post.Category = categories
.Where(p => p.PostId == postId)
.SingleOrDefault();
}
}
Ok. lets break this down.
First up, a nice connection inside a using block (so it's disposed of nicely).
Next, we make sure DEFERRED LOADING is off. Otherwise, when u try and do the set (eg. post.Category == blah) it will see that it's null, lazy-load the data (eg. do a rountrip the database) set the data and THEN override the what was just dragged down from the db, with the result of there Where(..) method. phew! Summary: make sure deferred loading is off for the scope of the query.
Last, for each post, iterate and set the category from the second list.
does that help?
EDIT
Fixed it so that it doesn't throw an enumeration error by calling the ToList() methods.
Just curious, if a Post have have one or many Categories, is it possible to instead of using the for loop, to load the Post.PostCategories with the list of Categories (one to many), all in one shot, using a JOIN?
var rslt = from p in results.GetResult<Post>()
join c in results.GetResult<Category>() on p.PostId = c.PostID
...
p.Categories.Add(c)