Grails searchable: search for a specific field in a member object?
Using the Grails Searchable plugin, I've got these classes:
class Person {
static searchable = {
address component: true
}
}
and:
class Address {
static searchable = {
root false
}
String country
}
I want to do a specific search for persons from a specific country. "count开发者_运维问答ry:NL" doesn't work. "address:country:NL" doesn't work either. I can't find anything about the syntax for this. Any ideas?
I think I'll have to do some clever indexing or some other trick in the searchable closure, but I just can't find it.
I created a basic app (Grails 1.3.5, Searchable 0.5.5.1) with your two classes and searching for 'country:NL' works for me. Did you remember to call index() before trying to search?
grails create-app search
grains install-plugin searchable
Person:
class Person {
static searchable = {
address component: true
}
Address address
}
Address:
class Address {
static belongsTo = Person
static searchable = {
root false
}
String country
}
Bootstrap:
class BootStrap {
def init = { servletContext ->
def p1 = new Person(address:new Address(country:'NL')).save()
def p2 = new Person(address:new Address(country:'DE')).save()
def p3 = new Person(address:new Address(country:'NZ')).save()
Person.index()
}
def destroy = {
}
}
Then I browsed to to /searchable and searched for country:NL and got person 1 returned.
If you want to see what Searchable is doing under the covers with regards to fields/indexes etc - Luke is a very handy tool (just download the executable JAR): http://code.google.com/p/luke/
The index files are in
<user.home>/.grails/projects/<project name>/searchable-index/development/index
cheers
Lee
The ugly solution that works: don't rely on Searchable. At the moment I first do a Person.search(params.query, [max:99999]).results
, then do simple .findAll to find by country and .sublist() to get paging to work again.
It's a shame it's so hard to get something so obvious to work with Searchable.
Another solution I haven't gotten to work is making country a transient property on Person that returns address.country. Didn't work out of the box, and I have no idea on how to fix it.
If anyone has any prettier solutions for me, I'd love to hear them.
I am new to grails but why do you have to use the searchable plugin ?
what is wrong with a simple 1:1 or 1:n relationship ?
package com.test
class Person {
static constraints = {
name (nullable:false)
address (nullable:true)
}
String name
Address address
String toString() {
"name[" + name + "]. address[" + address + "]"
}
static mapping = {
address lazy:false
}
}
class Address {
static constraints = {
country (nullable:false)
town (nullable:false)
}
String country
String town
//Person person
static belongsTo = [person:Person]
// static belongsTo = Person
String toString(){
"town[" + town + "], country[" + country + "]"
}
}
package com.test
import grails.test.*
class PersonIntegrationTestTests extends GrailsUnitTestCase {
protected void setUp() {
super.setUp()
}
protected void tearDown() {
super.tearDown()
}
void testSomething() {
def bill = new Person(name:'bill', address:new Address(town:'york', country:'UK')).save()
def fred = new Person(name:'fred', address:new Address(town:'leeds', country:'UK')).save()
def bjork = new Person(name:'helen', address:new Address(town:'helsinki', country:'finland')).save()
def gustav = new Person(name:'john', address:new Address(town:'helsinki', country:'finland')).save()
List ukAddresses = Address.findAllByCountry('UK') // find all by country
println "num addresses-" + ukAddresses.size()
for (int i in 0..<ukAddresses.size())
{
println "found person:" + ukAddresses[i].person
}
assertNotNull "bill can not ne null", bill
assertTrue bill.validate() && !bill.hasErrors()
assertTrue fred.validate() && !fred.hasErrors()
assertTrue bjork.validate() && !bjork.hasErrors()
assertTrue gustav.validate() && !gustav.hasErrors()
assertEquals 2, ukAddresses.size()
}
}
精彩评论