Projecting Grails Searchable plugin result set - grails

I have a complex searchable configuration for a domain class and its associated domain classes. when I search for about 200 results (max:200) it takes too long to respond.
in the result set I have all fields (simple or association) specified for search in my domain class. I need to return only an id list and ignore other fields of domain class. is it possible? I want to do this for speeding up my search. this id list will be used for querying another no-sql db. it seems that fetching all of the fields is slowing down my search.

I think you can achieve what you want (let the property be searchable but not return it) by setting the property store to no.
For example:
class MyDomain {
String name
String email
static searchable = {
email index:'analyzed', store:'no'
name index:'analyzed'
}
}
In this domain I say that name and email are indexed and analyzed (so they can be searched) but the email property is not being stored, so it will be null when the object is returned. For other properties check: http://grails.org/Searchable+Plugin+-+Mapping+-+Searchable+Property

Related

How to nullify the fields that fail validation and save the domain?

Suppose there is a domain as defined below.
class Book {
String title
Author author
}
Now, i save an instance of this domain. The author domain has some constraints. So, during save the validation for author fails now instead of not saving the whole domain i want to nullify the author(The author can be null) and save the title string as it was. In other words how do i nullify any number of fields whose validation failed and save rest of the properties values? Is there a convenient way to do so? Thanks!
This could be one of following :
In beforeInsert hook do something like below:
def beforeInsert() {
this.validate()
if(this.hasErrors()){
// get all errors and iterate through it and set the field to null for same
}
}
While saving the domain you could use
domain.save(validate:false)
Thanks!!

How to model stored procedure records in Grails?

I need to call some stored procedures that return their own kinds of records, that are not directly mapped to tables or views.
I have used stored procedures in the past with groovy.sql.Sql and plain (unmodelled) Maps, but for this application I would like to model those records with something akin to domain classes, in order to define data types, data binding, validation, associations to other entities, and so on.
What is the best way to do so?
Should I model the stored procedure records as proper domain classes (entities) and then try to disable (or redefine) their database persistence? How?
Should I use non-domain POJOs where I selectively enable the features I need? (such as validation with #Validatable) How can I handle associations then? (Associations arise when the record returned from the SP contains a foreign key to some other persisted entity.)
If you want data binding, validation and associations to be maintained in an easy way then you should go with the Domain approach.
To disable database persistence for a domain class you can add static mapWith = "none" to a domain class and a table won't be created for that domain class.
Sample Entity class:
#ToString
public class SPTest {
Long idField
User user
GroupIntegrationKey integrationKey
static constraints = {
}
static mapWith = "none"
}
Stored Procedure statement:
SELECT id AS idField, user_id AS user, key AS integrationKey FROM
my_domain;
In order to map the result of the SP to the entity you can use result transformers.
Query query = session.createSQLQuery("CALL getSPData()");
List<Map> results = query.with {
resultTransformer = AliasToEntityMapResultTransformer.INSTANCE
list()
}
Now iterate over list and create a new entity object
List<MyDomain> list = results.collect {
new MyDomain(it)
}
System.err.println(list)
Drawbacks:
You can not map identifier field
You would have to iterate over result again to create entity objects
You can not map hasMany relationships
If you want to go with pojo, then in that case you would have to create your own version of getters to get associated objects.

Grails binding one to one associations

When you generate grails views, grails looks at your relationships and generates the right html for your form data to be automatically binded to the back end domain. For one to one associations grails creates a drop down list.
However, you might not want to present that property as a drop down list but something more custom (for example a text field with autocomplete). As soon as you do that the value that comes to the controller from that field, comes in as a String and you have to first:
Clear errors
Perform a findBy based on a given param and assign it to the property of the domain
I really want to avoid doing findBys in the controller as much as possible because it seems like I am doing logic/things that should not go there. The controller should delegate to the Service layer. It is not clear to me from the grails documentation how would I do that by using bindData which seems to work really well with String, date, Integer properties etc.. but I do not see how bindData is used for properties that are other domains.
I also really want to avoid passing the params object to the Service layer as it seems less reusable (or maybe not, correct me if I am wrong). I guess that I do not like how it looks semantically. I would prefer the first over the second:
#Transactional
class WithdrawService {
def addWithdraw(Withdraw withdraw) {
//perform business logic here
}
def createWithdraw(Map params){
//perform business logic here
}
}
Let's take the following example:
class Withdraw {
Person person
Date withdrawDate
}
and the parent lookup table
class Person {
String name
String lastName
static constraints = {
}
#Override
public String toString() {
return "$name $lastName"
}
}
In order for the bind to happen automatically without any extra work grails passes in the following request params to automatically bind the one to one:
person.id
a person map with the id.
[person.id:2, person:[id:2], withdrawDate:date.struct, withdrawDate_month:11, create:Create, withdrawDate_year:2015, withdrawDate_day:10, action:save, format:null, controller:withdraw]
What is the best way to go about this?
Pass two hidden fields that look exactly like this: person.id:2, person:[id:2] that get populated as a result of the Ajax call that populates the autocomplete?
In the controller do a Person.findBySomeKnownProperty(params.someKnownValue)
Or any other approach?

can we have multiple aliases for a Domain Class Attribute in grails

I have many domain classes in my application an for Audit logging I need the name attribute of each Domain class. unfortunately the name attribute is not generic in all Domains.
In my Audt log class I get the type of object modified/created/deleted and then save the id right now (which is common code since all domains have 'id' attribute) but now if I want to get the name attribute out of the domain from the ID, each domain has a different name attribute, like Resource Domain has resourceName, User domain has userName and so on... soI will have to handle each domain seperately (like have a map or bunch of switch statements for getting the name attribute from the Domain class name).
Is there a way I can have an alias mapping for each domain class's name field to be called 'name' . there should not be any change to the actual attributes in the Domains in whatever changes I do, I can add a column to Audit Domain but not other table changes.
Thanks in Advance
I don't think that there's any way to do this automatically.
As you guessed, you're going to either have to change all of the domain objects so that they have a 'name' attribute, or somehow maintain a map of which attribute in each class is to be considered the 'name'.
I suppose that one answer might be to add a getName() method to each of the domain classes, and return the appropriate value from that method.
If you really don't want to modify the domain objects at all, you can use groovy meta-object programming (MOP) to inject this method into each domain class from the BootStrap class.

Dynamic MongoDb queries in Grails

I have a domain similar to this in Grails
class User {
static mapWith = "mongo"
ObjectId id
String name
String address
Integer age
}
I am building a search front-end in Grails to query a MongoDb database using the MongoDb plugin. Searching can be done on any of the fields in the database and any field that is not set by the user must be not be used in the query. I.e. no fields shall be compared to null. For example leaving all the fields empty returns all Users but searching for name returns only documents which matches on name.
Initially my queries was simple and I used User.find(new User(params)); in my controller which worked fine. Now I need to be able to also query integer fields using intervals, greater than and less than. I've looked at withCriteria() and to build the query depending on what fields the user have set but so far I've been unsuccessful.
TL;DR
How can I do a query where I don't know which fields the user want to include in the query?
I solved it by using withCriteria() like this:
def c = User.createCriteria()
def users = c.list {
if(params.name)
eq('name', params.name)
if(params.address)
eq('address', params.address)
if(params.age_gt?.isInteger())
gt('age', params.age_gt as Integer)
if(params.age_lt?.isInteger())
lt('age', params.age_lt as Integer)
}

Resources