How to search an inner class? - grails

I have these classes.
class Author{
Person person
}
class Person{
String lastName
String firstName
String middleName
}
I'd like to query Person and Author.
def persons = Person.findAllByLastNameiLike("${a}")
but it seems I can't do
def authors = Author.findAllByPerson(persons)
Any ideas how I'd do this?

This code shown above does not work
def authors = Author.findAllByPerson(persons)
because findAllBy* works with a single object, not a collection. To find all authors where the Person is any one of those contained in persons use either HQL or a criteria query. For example an (untested) HQL query would look something like:
Author.executeQuery("""
FROM Author a
WHERE a.person IN (:people)""", [people: persons])

Related

Neomodel filter on relationship

I'm having trouble figuring out the most efficient way to filter a Neomodel NodeSet based on a relationship. I have a class Patient that has a relationship GENDER that points to a node with the label Gender.
My classes looks like this:
Class Patient(StructuredNode):
patient_id = StringProperty()
gender = RelationshipTo('Gender', "GENDER")
Class Gender(StructuredNode):
gender = StringProperty()
patient = RelationshipTo('Patient', "HAS")
I start by filtering Patient by a query string which returns a NodeSet called patients. I now want to filter patients by gender. What I have is:
patients = NodeSet((NodeSet(patients.gender).filter(gender=gender).patient)
This works but I'm wondering if there is an easier way or better way??

HQL Join in Grails

I am trying to execute a query to gather specific data but encountering problems in the query on the on portion of the query. To start off this is my class:
class TimeSlot {
String timeslot_id
String time_chunk_id
String uid
String exam_id
String start_time
String is_special_arrangement
static mapping = {
table 'timeslot'
id name: "timeslot_id", column: "timeslot_id"
version false
}
}
This is the query I'm trying to get working:
TimeSlot.executeQuery("Select t.time_chunk_id, t.uid, t.start_time, t.timeslot_id, t.is_special_arrangement, e.length from TimeSlot t inner join Exams e on t.exam_id = e.exam_id where t.exam_id = ? and t.time_chunk_id = ?", [testArray[i], timeChunkArray[x]])
It's throwing an error on the on portion because it's expecting a clause, but I need the data to specifically pertain to the exam.id comparison of both tables. Is there another way around this or a different way to set up the query so it will work like it does in any SQL editor?
It would be easier if you alter the domain class and add one to many relationship
class TimeSlot {
static hasMany = [examinations:Exams]
Then HQL can be
select ... from TimeSlot t join t.examinations e

A oneToMany join in Grails using findAll or HQL

I'm new to Groovy and HQL querying but I can't find a solution to this anywhere so it's driving me nuts.
I have two Domain classes which have a one to many relationship defined (a user can have many companies) and I effectively need to do (what would traditionally be called) 'a table join' but clearly with objects.
The classes go like this:
class User {
transient springSecurityService
static hasMany = [company: Company]
String username
String password
boolean enabled
boolean accountExpired
boolean accountLocked
boolean passwordExpired
...
...
...
}
... and the company class
class Company {
static scaffolding = true
String name
String address1
String address2
String address3
String address4
String postCode
String telephone
String mobile // mobile number to receive appointment text messages to
String email // email address to receive appointment emails to
static hasMany = [staff: Staff]
static belongsTo = [user: User]
...
...
...
}
Gorm has created an user_id field within the company table but any attempt to use this in a query returns an error.
So how would I do something like:
select * from user u, company c, where u.id = c.user_id;
What is the best way to do this?
You can effectively use join on the association something like:
HQL
select * from User as u inner join fetch u.company as companies where u.id = ?
Note that using fetch in the query would eagerly fetch the associated collections of companies for a user
findAll()
User.findAll("from User as u inner join fetch u.company as companies where u.id = ?", [1])
Benefit of using findAll instead of HQL is that you can easily implement pagination something like:
User.findAll("from User as u inner join fetch u.company as companies where u.accountExpired = true", [max: 10, offset: 5])
To get a concrete implementation and really understand things in details I would insist to have a look at findAll and HQL associations.

Filtering on multiple associations and optional where clauses

I've got a several domain classes, with some simple associations between them as follows:
class Business {
String name
City city
Industry industry
}
class City {
String name
}
class Industry {
String name
}
In my application, I would like to have a "filter" where the list of all businesses can be filtered according to the City and Industry. I am able to get the City and Industry id's from the filter back to the Business controller, however, when I get to the controller to do the filtering, I have this code:
...
def industry = Industry.get(params.int('industryid'))
def city = City.get(params.int('cityid'))
def businessList = Business.findAllByIndustryAndCity(industry, city)
...
This code works when both the City and Industry fields have values. However, sometimes the user might want to just filter by city or industry and not both. In this case, the filter fails, as when either of the values are null no results are returned. How could I specify that if either of the association values are "null", then the "find" query should remove this constraint altogether? i.e. match "all" for that field
Note that I realise that it would be easy to put an if statement checking whether the values are null and then executing a different "find" statement based on that. However, while this would work with two values, I don't think it would scale well as more filterable values are added.
You can build criteria.
def c = Business.createCriteria()
def results = c.list{
and {
if (industry) {
eq("industry", industry)
}
if (city) {
eq("city", city)
}
}
}
Check reference here in grails docs.
However your code needs N+1 queries for N parameters. Maybe you can reduce it to one query using criteria idea? If your Business entity holds foreign keys to both Industry and City this one should work:
def c = Business.createCriteria()
def results = c.list{
and {
if (params.industryid) {
eq("industry_id", params.industryId as Long)
}
if (params.cityid) {
eq("city_id", params.cityid as Long)
}
}
}
Both examples are untested but you should get the idea.

Using hasMany in grails and postgresql

I have a postgresql database that has this column structure:
Author
id
name
Book
id
name
author_id
And Groovy Domain Classes that repressent those tables:
class Author {
static hasMany = [ books : Book ]
Integer id
String name
}
class Book {
static belongsTo = Author
Integer id
Integer project_id
String name
}
My main goal to get a list of books from a author instance.
author = Author.get( 1 ) // gets a author
author.books // must return a list of books.
But this does not work. Is there something glaringly obvious I'm doing wrong?
note I've got lots of Ruby/Rails experience and zull Java/Groovy experience.
Change your Book class to:
class Book {
static belongsTo = [authors: Author]
static mapping = {
authors column: 'author_id'
}
Integer id
Integer project_id
String name
}
If you don't specify the mapping like that, GORM will create, resp., expect, a JOIN table by default.
(BTW, domain classes are automatically provided with a "virtual" id property (of type Long I think, translating to bigint in PostgreSQL). It's not necessary to specify it manually, but it also won't harm.)
EDIT: Updated as per the questioners comments:
If a book can really have just one author, you'd state in the Book class:
Author author
static belongsTo = [author: Author]
static mapping = { author column: 'author_id' }
The GORM documentation on one-to-many relations can be found here.

Resources