Grails Searchable plugin with Criteria - grails

I have some question about searchable plugin :
i have two domain :
class Ads {
static searchable = true
String fromCity
String toCity
User user
static constraints = {
}
}
class User {
String username
String password
}
And i have developed my own search page with two field (fromCity,toCity) . to have something like :
def listResults = searchableService.search("NewYork","Miami")
So I would like to know how I can give to my search method this to Criteria Field.
def srchResults = searchableService.search(??????)
I'll be so grateful if someone can help me to do this.

First you need to define a searchable closure in your domain class. For instance
static searchable = {
analyzer "simple"
only = ['firstName','uuid']
firstName boost: 5.0
}
Then you can search as follow.
def searchResults = SomeDomain.search(textToSearch + "*" + " -(firstName: ${myName})", params)
-(firstName: ${myName}) this remove the my name from the search result, similarly you can and or other fields depending on your logic.
The default operator is "and" where as you can modify the operator, see following example
defaultOperator - Either "and" or "or". Default is to defer to the global Compass setting, which is "and" if not otherwise set by you.
search("mango chutney", defaultOperator: "or")
// ==> as if the query was "mango OR chutney"
// without the option it would be like "mango AND chutney"
For more detail please see the documentation.
Searchable Plugin Documentation
Let me know if you need any help.
More Help On Compass
See section 12.5.1. Query String Syntax

Related

Grails GORM find by value inside map of Domain

I am using Grails 2.2.4 and having one Domain contains value as map and I want to find domain object using key of map. Please help me to resolve this issue.
Student.groovy
package com.grails
import java.util.Map;
class Student {
String firstName
String lastName
Map address
static constraints = {
}
}
When My application are run I can see that Grails application create tables in database are as follow:
1) first table
student
id
version
first_name
last_name
indexes
2) second table
student_address
address
addres_idx
addres_elt
When I save Domain as:
def std = new Student()
std.firstName = 'Piyush'
std.lastName = 'Chaudhari'
std.address = [city:'Surat',state:'Gujarat',pincode:'38001']
std.save(flash:true)
values are insert in database as follow:
student table
ID VERSION FIRST_NAME LAST_NAME
1 0 Piyush Chaudhari
student_address table
ADDRESS ADDRESS_IDX ADDRESS_ELT
1 city Surat
1 state Gujarat
1 pincode 38001
Now, I want data or row using GORM like Student.findBy_____ or Student.findAllBy______
where 'city' = surat
Any one can help me to resolved this issue?
You can use:
Student.findBy<FieldName1>And<FieldName2> (<FieldNameParameter1>, <FieldNameParameter2>)
Or Either:`
Student.list().find { it.address.city == 'Surat' }
Student.list().findAll { it.address.city == 'Surat' }
`
I don't think that you can search things like this using maps.
Maybe you can do this:
def students = Student.list()
def result = students.each { student -> student.address.city == 'Surat' }
println("Resultado" + result)
But this is a very bad way to do this kind of things
Define an address class, and then add an address field to the student class (this will change how your tables are mapped in the database):
class Student {
String firstName
String lastName
Address address
static constraints = {
}
}
class Address {
String city
String state
String pincode
}
Address should be another entity in your domain, not a map of values. Remember that Grails GROM is an ORM, so you should design your domain using a OOP model in order to take advantage of the dynamic finders and criterias for doing queries.
With those changes in place, you can now use a simple criteria:
def students = Student.withCriteria{
'address'{
eq('city', 'surat')
}
}
More information about criterias in the grails docs:
http://grails.org/doc/latest/ref/Domain%20Classes/withCriteria.html
http://grails.org/doc/latest/guide/single.html#criteria
If you want to use Dynamic finders, you will have to get all the address with city = 'surat' and then use a findByAddressInList(...). But i think that in this case, criterias is a better approach

GORM querying: findAllByPropertyNotInList or findByPropertyNotInList do not exist, any equivalency?

The next code works:
self query1 = DomainClassExample.findAllByPropertyInList("hi","bye")
But if I add Not, the dynamic finder does not exist (it DOES exists: check the answer):
self query2 = DomainClassExample.findAllByPropertyNotInList("hi","bye")
I want to get all the DomainClassExample which don't have the property "hi" or "bye". Is there any dynamic finder for that purpose? Should I use the Where Query. How?
First, a minor correction. It's not a method expression. It's a dynamic finder. Now, as to your actual problem, you'll need to use the criteria API for this...
def c = DomainClassExample.createCriteria()
def matchingProperties = c.list {
property {
not { 'in'(["hi","bye"]) }
}
}
You might run into an issue with the word 'property' and I haven't actually tested the code I just wrote. But that is the gist of it.
In Grails 1.3.9, given the following domain:
class User {
String username
....
}
this works in our application without any issues:
def userList = User.findAllByUsernameNotInList(["user1#testdomain.com","user2#anotherdomain.com"])

Grails findBy multiple columns Ilike

I have a simple Tag class with only two fields, name and value,
class Tag {
String name
String value
}
and I'm trying to render an XML where I want to search for parts of both parameters via findBy...Ilike().
def getXml = {
render Tag.findAllByNameAndValueIlike("%${params.name}%", "%${params.value}%") as XML
}
But this doesn't give my any results. If I use only one parameter, it works as I expect:
def getXml = {
render Tag.findAllByNameIlike("%${params.name}%") as XML
}
My next question is probably going to be about filtering the results, and adding other "similar" tags to the returns list, so is there a way to solve the above with something like:
def getXml = {
list = Tag.findAllByNameIlike("%${params.name}%")
list.add(Some other stuff)
list.sortBy(Some thing, maby name length)
}
For your multiple-field ilike query you can use withCriteria:
def result = Tag.withCriteria {
ilike('name', "%${params.name}%")
ilike('value', "%${params.value}%")
}
This will return a list of Tag domains whose name matches the provided name and value matches the provided value.
The Criteria DSL will probably let you do most of the filtering you need, but you can also consider using some of the Groovy collection examples here.
You have to put the restrictions(InList, NotNull, etc) on each field of a dynamic finder. If you do not, it assumes equals. Here is what you were looking for:
Tag.findAllByNameIlikeAndValueIlike("%${params.name}%", "%${params.value}%")
Both answer are good. I tried both, but I have to say I like the withcCritia the best. It seems very flexibly.
def result = Tag.withCriteria {
if(params.name != null)
ilike('name', "%${params.name}%")
if(params.value != null)
ilike('value', "%${params.value}%")
}
result.add(new Tag('name': "something"))
render result as XML

Grails gorm: queries with map

Having the following domain class:
class Word {
Map translations
}
And instances in BootStrap:
def word1 = new Word().with{
translations = [en:"game"]
save(failOnError: true, flush: true)
}
def word2 = new Word().with{
translations = [en:"life"]
save(failOnError: true, flush: true)
}
What is the groovy way to get all words, where translation starts with startPart in some locale? For example:
def listWordsStartsWith(startPart, locale, params){
def regexp = startPart+'%'
def query = Word.where {
//translations[locale] =~ regexp
}
def words = query.list(params)
words
}
I don't think this is possible with GORM using a collection value for the translations field. I'd suggest the following alternate mapping:
class Word {
static hasMany = [translations: Translation]
}
class Translation {
static belongsTo = Word
String key
String value
}
Then the query would be something like this:
Word.createCriteria().list {
translations {
like('key', startPart+'%')
}
}
The where wethod relies on Groovy SQL, where you have a very small subset of Groovy. It maps the SQL commands, but allow IDE controls on the properties and well formed syntax.
Unfortunately, you cannot write all the Groovy inside (no function, few operators, no map, etc.).
Check the documentation to see what is accepted.

Grails criteria builder

I have the folowing:
class Store{
String name
}
class Shop{
String name
Store store
}
My criteria builder:
def c = Shop.createCriteria()
def results = c.list {
like("name", "Harrods")
like("store.name", "McDonals")
}
I'm sure this is invalid cause i'v tested it. How can i manage to use criteriaBuilder and do this: like("store.name", "McDonals")?
Looking forward to get any help,
John
Since you're querying an association, try:
def results = c.list {
like('name', 'Harrods')
store {
like('name', 'McDonals')
}
}
This will do an conjoined query between name and store.name.
Check out the documentation Looks like you need to use a % for your like clause.

Resources