One's more about grails searchable plugin - grails

I have two simple domains:
public class Hotel {
static searchable = true
Source source
City city
HotelType type
long sourceid
float lat
float lon
static hasMany = [hotelTexts:HotelText]
static mapping = {
hotelTexts batchSize:10
}
}
public class HotelText {
static searchable = true
static belongsTo = [hotel:Hotel]
String lang
String name
String description
String address
static mapping = {
batchSize:10
description type:"text"
}
}
I'm totally new in searchable plugin but i believe that it could help me with my problem.
So, the task is to find Hotels by city and then sort result by name. Without sorting it could be easily done with dynamic finders help but...
Summary:
Find hotels by city.
Sort result by hotel name(for given language).
Support pagination.

public class Hotel {
static searchable = {
hotelTexts component: true
}
...
}
public class HotelText {
static searchable = {
name boost: 2.0
}
...
}

Related

How to get value in my show page in Grails

How to get the value as following codes with my show view page on Grails?
Person.groovy
package com
class Person {
String person
static constraints = {
person blank:false,nullable:true
}
static hasMany=[task:Task]
String toString(){return person}
static mapping={
}
}
Task.groovy
package com.moog
class Task {
String task
static constraints = {
task blank:false,nullable:true,unique:true
}
static belongsTo=[person:Person]
static hasMany=[tag:Tag]
String toString(){return task}
}
Tag.groovy
package com
class Tag {
String tag
static constraints = {
tag blank:false, nullable:true
}
static belongsTo=[task:Task]
String toString(){
return tag
}
}
First of all try a better wording for your collections
static hasMany=[tasks:Task] // in Person.groovy
static hasMany=[tags:Tag] // in Task.groovy
In your person show.gsp try something like
<g:each in=${person.tasks} var="task">
<p>${task}</p>
</g:each>
If you do not use scaffolding and write you own controller methods to create your entities than maybe this helps you further:
def task = new Task(task:"Clean room")
def person = Person.get(1)
person.addToTasks(task)
person.save()

Grails createCriteria on abstract domain

I am quite curious how one would use the criteria builder to access fields of an inherited class.
Let's assume we have the following class:
class A {
String fieldOne
String fieldTwo
static hasMany = [childs: AbstractChildClass]
}
and the abstract child class would look like this:
abstract class AbstractChildClass {
Integer valueOne
Integer valueTwo
A a
static mapping
tablePerHierarchy false
}
}
of course there are several extending classes such as:
class ExtendingClassOne extends AbstractChildClass {
DesiredObject desiredObject
static mapping = {
tablePerHierarchy false
}
}
let's also assume there is the class DesiredObject which looks like this:
class DesiredObject {
String infoA
String infoB
}
The question is how one would get the fields infoA and infoB by creating a criteria for class A. My approach so far is this:
A.createCriteria().list {
childs {
desiredObject {
ilike('infoA', '%something%')
}
}
}
This of course does not work because in the table ExtendingClassOne is only the id of the desiredObject and I have no clue how to join the object with the criteria builder to get its fields.
Thank you for reading.
Marco
don't expect 100% match between your domain model and the DB schema it's related to.
In your case the polymorphism would work only with tablePerHierarchy true for AbstractChildClass.
If you do want to stick with tablePerHierarchy false, you can define your class like:
class A {
static hasMany = [ childrenOne:ExtendingClassOne, childrenTwo:ExtendingClassTwo ]
}
thus your query would be as simple as:
A.withCriteria{
for( String c in [ 'childrenOne', 'childrenTwo' ] ){
"$c"{
desiredObject {
ilike('infoA', '%something%')
}
}
}
}

How to limit the size of association in grails?

I have a grails domain class as below :
class Order {
String orderId = 'OD' + System.nanoTime().toString()
Date orderedDate
String itemName
List bids;
static hasMany = [ bids: Bid ;likedUsers: User,]
static belongsTo =[owner:User]
}
class Bid {
Integer amount
User bidedUser
static belongsTo = [Order]
}
class User {
String username
String password
String emailId
List orders
static hasMany = [orders:Order]
}
What I am trying to do is , to query for an order with bits with maxResult of 10 as like
def critObj = Order.createCriteria()
critObj.list{
eq("id" ,1)
bids {
maxResult(10) //Trying to fetch only 10 records
}
}
How can I load only 10 bits(associations) , is it possible? . Or My design of domain class is wrong?
I think this should work:
def results = Bid.withCriteria {
order {
eq 'id', 1
}
projections {
property 'order'
}
maxResults 10
}
But please note that you have to change your Bid domain class to add the relation in the other way from Bid to Order:
class Bid {
...
static belongsTo = [order: Order]
}

inheritance in Grails domain model

My Grails app's domain model has the following requirements:
a user belong to zero or one organisations
an organisation is either a charity or a company
charities and companies have some some common fields and also some (non-nullable) fields that are unique to each organisation type
I put the common organisation fields into an abstract Organisation class which Charity and Company both extend. I can't store this hierarchy in a single table because there are non-nullable fields that are specific to each organisation type. The relevant parts of the domain model are shown below:
class User {
String name
static belongsTo = [organization: Organization]
static constraints = {
organization nullable: true
}
}
abstract class Organization {
String name
static hasMany = [users: User]
static mapping = {
tablePerHierarchy false
}
}
class Charity extends Organization {
// charity-specific fields go here
}
class Company extends Organization {
// company-specific fields go here
}
When I look at the MySQL schema generated from this model, the inheritance relationship between organisation-company and organisation-charity seems to have been completely ignored. Although there is an organisation table with a name column, it has no primary-foreign key relationship with either company or charity
I see the same result as IanRoberts for both MySQL and H2. In other words: no join table generated, but the expected organization_id FK in the users table.
With "Table per subclass" mapping (tablePerHierarchy false), you end up with an implied one-to-one relationship in the database. Primary Keys for Charity and Company will have the same value as the PK for the parent Organization. The schema generated by GORM/Hibernate3 doesn't appear to enforce this with referential integrity constraints. It's pure Hibernate magic. A bit more detail here
Solved!
Add the class below to src/java (this class cannot be written in Groovy)
package org.example;
import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration;
import org.hibernate.MappingException;
import org.hibernate.mapping.JoinedSubclass;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.RootClass;
import java.util.Iterator;
public class TablePerSubclassConfiguration extends GrailsAnnotationConfiguration {
private static final long serialVersionUID = 1;
private boolean alreadyProcessed = false;
#Override
protected void secondPassCompile() throws MappingException {
super.secondPassCompile();
if (alreadyProcessed) {
return;
}
for (PersistentClass persistentClass : classes.values()) {
if (persistentClass instanceof RootClass) {
RootClass rootClass = (RootClass) persistentClass;
if (rootClass.hasSubclasses()) {
Iterator subclasses = rootClass.getSubclassIterator();
while (subclasses.hasNext()) {
Object subclass = subclasses.next();
// This test ensures that foreign keys will only be created for subclasses that are
// mapped using "table per subclass"
if (subclass instanceof JoinedSubclass) {
JoinedSubclass joinedSubclass = (JoinedSubclass) subclass;
joinedSubclass.createForeignKey();
}
}
}
}
}
alreadyProcessed = true;
}
}
Then in DataSource.groovy set this as the configuration class
dataSource {
configClass = 'org.example.TablePerSubclassConfiguration'
pooled = true
driverClassName = "org.h2.Driver"
username = "sa"
password = ""
dbCreate = "update"
url = "jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000"
}
I've submitted a pull request to Grails that fixes this. The fix was be included in Grails 2.3.9.
ORM is not RDBS.
tablePerHierarchy false
so You Have three tables: Organization, Charity, Company. User belongs to only Organization (not Charity or Company). How are you going to get value of specific fields?
There is USER. We know ORGANIZATION, but we don't know Charity or Company. I think you underst...
I can suggest you three solutions:
1. tablePerHierarchy true (But you need to have nullable charity\Company -specific fields )
2.
class User {
static belongsTo = [charity: Charity, company: Company]
}
class Charity {
String name
static hasMany = [users: User]
// charity-specific fields go here
}
class Company {
String name
static hasMany = [users: User]
// company-specific fields go here
}
3.
class User {
static belongsTo = [organization: Organization]
}
class Organization {
String name
Charity charity //nullable
Company company //nullable
static hasMany = [users: User]
}
class Charity {
static belongsTo = [organization: Organization]
// charity-specific fields go here
}
class Company {
static belongsTo = [organization: Organization]
// company-specific fields go here
}

Grails criteria select when hasMany hasn't any elements

I have the classes:
class Course{
String name
static hasMany = [
studentGrades: StudentGrade
]
}
class StudentGrade{
String name
int grade
}
How can I make a criteria to get the courses without any student grade?
You could use the isEmpty criterion method:
def c = Course.createCriteria()
def results = c.list {
isEmpty("studentGrades")
}
See the docs for further informations.

Resources