how to use "where...in" in subsonicproject - subsonic3

I am using subsonicproject and the activerecord pattern.
I have a database with three tables: Cities, Concerthalls, Concerts. Each Concerthall has a foreign-key relationship to a City. Each Concert has a foreign-key relationship to a Concerthall.
I would like to retrieve all concerts within a given city. So I need to get all the Concerthall-ids for a city and pass them to subsonicproject. In "normal" sql I would use the "where ... in"-statement, but how do I do it with subsonicproject?
I am thinking about something like (pseudocode):
List concertHallsId=xxxxxxx;
Concerts.Find(concert.ConcertHallId in concertHallIds);
thanks
Thomas

You should be able to do something like:
var concertHallIds = new List<int>() { 1, 2, 3 };
var concerts = from c in db.concerts
where concertHallIds.Contains(c.ConcertHallId)
select c;
At least, that is the Linq version. Basically though, you should be ale to use .Contains() on your collection of concert hall ids, and SS puts those values into an in clause in the SQL.

Related

using inner join criteria language

Have two tables : Rating and Books. Rating table has foreign key to the Books table.
These tables are mapped this way :
Books :
HasMany(x => x.RatingList).Cascade.All().Inverse();
and the Rating table :
References(x => x.Books).Column("BookId").Cascade.All();
Have this :
var bks = session.CreateCriteria("Books", "b");
using this restriction for selecting books
bks.Add(Restrictions.Eq("CategoryId",id));
here is the problem, how to join Rating table ??
bks.CreateAlias("b.Rating", "c");
bks.List();
return PartialView("/Views/Home/_Books.cshtml", bks);
The final result i need is to select all Books but also Rating for them. In the Rating table has many ratings for one book. Book rating should be given as average of ratings.
Some help ?
A criteria lets to retrieve a list of a specific class, in your case List<Book>. So, you are asking hibernate to retrieve a book list, not a list of books and ratings.
Of course, you can access ratings for every book into the resulting list. If it doesn't work, maybe a LazyInitialitationException happens. In this case you will have to apply OSIVF, extends session lifetime, or whatever.
Criteria lets you join entities to filter query results. If you create an alias for ratings, it is because you want to filter results with an ratings attributes, but it won't include ratings into the resulting list.

Django select rows with duplicate field values for specific foreign key

again I would like to search for duplicates in my models, but now slightly different case.
Here are my models:
class Concept(models.Model):
main_name = models.ForeignKey(Literal)
...
class Literal(models.Model):
name = models.Charfield(...)
concept = models.ForeignKey(Concept)
...
And now the task I'm trying to achieve:
Select all literals that are NOT main_names, that have the same name for the same concept.
For example if I have literals:
[{id:1, name:'test', concept:1}, {id:2, name:'test', concept:1}]
and concepts:
[{id:1, main_name:1}]
Then in result I should get literal with the ID=2.
It sounds to me as though you want to execute a SQL query something like this:
SELECT l1.* FROM myapp_literal AS l1,
myapp_literal AS l2
WHERE l1.id <> l2.id
AND l1.name = l2.name
AND l1.concept = l2.concept
AND l1.id NOT IN (SELECT main_name FROM myapp_concept)
GROUP BY l1.id
Well, in cases where the query is too complex to easily express in Django's query language, you can always ask Django to do a raw SQL query—and this may be one of those cases.
If I understand your question you want:
All Literal objects that are not ForeignKey'd to Concept.
From that set, select those where the name and the concept is the same.
If so, I think this should work:
For the first part:
q = Literal.objects.exclude(pk__in=Concept.objects.values_list('id', flat=True))
EDIT:
Based on excellent feedback from Jan, I think for #2 you would need to use raw SQL.

JPA JPQL: select items when attribute of item (list/set) contains another item

public class Document extends Model {
...
#ManyToMany
public Set<User> accessors;
...
}
I want to select all Documents which accessors contain a certain user.
I have just minimal experiences with SQL and no experiences with JPQL.
So how to do that?
thanks in advance
SELECT d FROM Document AS d WHERE :user MEMBER OF d.accessors
Should be what you need, and it is simpler than joining tables.
Just dont forget to use the user as a parameter instead of using its id:
query.setParameter("user", user);
select distinct d from Document d inner join d.accessors a where a.id = :id
You should learn how SQL joins work, and then learn how to use joins in JPQL. That's essential. You'll find plenty of tutorials online. Google is your friend.

Sort by number of matches on queries based on m2m field

I hope the title is not misleading.
Anyway, I have two models, both have m2m relationships with a third model.
class Model1: keywords = m2m(Keyword)
class Model2: keywords = m2m(Keyword)
Given the keywords for a Model2 instance like this:
keywords2 = model2_instance.keywords.all()
I need to retrieve the Model1 instances which have at least a keyword that is in keywords2, something like:
Model1.objects.filter(keywords__in=keywords2)
and sort them by the number of keywords that match (dont think its possible via 'in' field lookup). Question is, how do i do this?
I'm thinking of just manually interating through each of Model1 instances, appending them to a dictionary of results for every match, but I need this to scale, for say tens of thousands of records. Here is how I imagined it would be like:
result = {}
keywords2_ids = model2.keywords.all().values_list('id',flat=True)
for model1 in Model1.objects.all():
keywords_matched = model1.keywords.filter(id__in=keywords2_ids).count()
objs = result.get(str(keywords_matched), [])
result[str(keywords_matched)] = objs.append(obj)
There must be an faster way to do this. Any ideas?
You can just switch to raw SQL. What you have to do is to write a custom manager for Model1 to return the sorted set of ids of Model1 objects based on the keyword match counts. The SQL is simple as joining the two many to many tables(Django automatically creates a table to represent a many to many relationship) on keyword ids and then grouping on Model1 ids for COUNT sql function. Then using an ORDER BY clause on those counts will produce the sorted Model1 id list you need. In MySQL,
SELECT appname_model1_keywords.model1_id, count(*) as match_count FROM appname_model1_keywords
JOIN appname_model2_keywords
ON (appname_model1_keywords.keyword_id = appname_model2_keywords.keyword_id)
WHERE appname_model2_keywords.model2_id = model2_object_id
GROUP BY appname_model1_keywords.model1_id
ORDER BY match_count
Here model2_object_id is the model2_instance id. This will definitely be faster and more scalable.

Filter for elements using exists through a reverse foreign key relationship

A relevant image of my model is here: http://i.stack.imgur.com/xzsVU.png
I need to make a queryset that contains all cats who have an associated person with a role of "owner" and a name of "bob".
The sql for this would be shown below.
select * from cat where exists
(select 1 from person inner join role where
person.name="bob" and role.name="owner");
This problem can be solved in two sql queries with the following django filters.
people = Person.objects.filter(name="bob", role__name="owner")
ids = [p.id for p in people]
cats = Cat.objects.filter(id__in=ids)
My actual setup is more complex than this and is dealing with a large dataset. Is there a way to do this with one query? If it is impossible, what is the efficient alternative?
I'm pretty sure this is your query:
cats = Cat.objects.filter(person__name='bob', person__role__name='owner')
read here about look ups spanning relationships