Grails Detached Criteria with Composite key - grails

Domain Setup
.
Study {
Long id
String name
Site site
USState state
...
}
.
Site {
Long id
String name
...
}
.
Resource {
Long id
String name
Boolean active
USState state
...
}
.
SiteResource {
id composite: ['site', 'resource']
Site site
Resource resource
}
I have 2 lists that get populated for the Study.
One is a list of currently associated Resources to the Site
Another is a list of available Resources that can be associated to the Site. These available Resources are determined by being Active = true and within the same USState as the Study
I'm trying to write a criteria to get this to work but cannot seem to get it. I need to show all Resources that are Active, in the same USState as the Study and not currently associated with the Site (the current associations are in the first table)
return Resource.createCriteria().list(sort: params.sort, order: params.order, max: params.max, offset: params.offset) {
if (params.searchText) {
ilike("name", "%${params.searchText}%")
}
eq("usState", params.state)
eq("active", true)
ne "id" , new DetachedCriteria(SiteResource).build {
'in' ("resource", params.associatedResources.resource.id)
'in' ("site", params.associatedResources.site.id)
}
}
I've also tried the following:
def siteResources = getSiteResourcesBySite(site).collect {
it.resource
}
def resources = resource.findAllByRefugeAndActiveNotInList(refuge, true, siteResources, [sort:"name"])
return resources.list(sort: params.sort, order: params.order, max: params.max, offset: params.offset)
I hope this made sense; I'm still trying to figure out how the DetachedQuery works. If there is a better way to accomplish this task please enlighten me!

Criteria builder was not needed. Here's my solution:
def site = siteService.getSite(params.siteId)
def stateCode = site.study.state.code
def state= State.findByCode(stateCode )
List<Resource> associatedResources = siteResourceService.getAssociatedResourcesBySite(site).collect { it.id }
params.state = state
params.site = site
...
def getUnassociatedResourcesByState(params, List associatedResources) {
params.max = Math.min(params.max ? Integer.parseInt(params.max) : 25, 100)
params.offset = params.offset ? params.offset : 0
params.sort = params.sort ? params.sort : 'name'
params.order = params.order == 'desc' ? params.order : 'asc'
return Resource.findAllByStateAndActiveAndIdNotInList(params.state, true, associatedResources, [sort: params.sort, order: params.order, max: params.max, offset: params.offset])
}

Related

ElasticSearch: A query that allows nil parameters

So i have the below module in an ElasticSearch concern for my Model in rails.
This is working, but how do I make each of the bool query(must, must_not, filter) accept nil or empty parameters?
Say if I pass an empty query_string it would get all the documents.
Then when I pass an empty size parameter it will return all sizes.
module ClassMethods
def home_page_search(query_string, size, start_date, end_date)
search({
query: {
bool: {
must: [
{
multi_match: {
query: query_string,
fields: [:brand, :name, :notes, :size_notes]
}
}
],
must_not: [
range: {
unavailable_dates: { gte: start_date, lte: end_date }
}
],
filter: [
{ term: { size: size } }
]
}
}
})
end
end
I solved a similar problem by constructing the query string on more of an as-needed basis, so I only included a clause if there was a search term for it. The query I sent to Elasticsearch only included the terms that were actually set by the user. For example:
if size.present?
query[:query][:bool][:filter] = { term: { size: size } }
end
(assuming the correct representation of the query, etc.)

Find data in list (Filter)

I have a list with fields
I need to filter only on a specific parameter
Model:
class Doc {
static constraints = {
name()
parameter(inList: ["Список",
"Строка",
"Число"])
}
String name
List parameter
}
In index.gsp
<label for="query">Where:</label>
<g:select value="${params.parameter}" name="parameter" from="${parameterList}" noSelection="['':'All parameter']" />
In controller
def index(Integer max) {
params.max = Math.min(params.max ? params.int('max') : 2, 10)
def parameterList = Doc.parameter.list()
if (params.parameter != "" ) {
def item = parameterList.find { p -> inList(p.parameter, "%${params.parameter}%")}
}
[params: params, parameterList: parameterList]
}
That is, for example
There are data:
name: a1 parameter: [[list], [string]]
name: a2 parameter: [[list], [number]]
name: a3 parameter: [number]
I choose to filter by "number" and I only need to get two values of "a2" and "a3"
//your params data sample (not sure about this point)
def params=[
a1: ['123','234'],
a2: [123,234],
a3: 123,
a4: '123',
]
//the filter
def filter = "number"
//map from filter to filtering class
def filterClazz = [
number: Number.class,
string: CharSequence.class,
].get(filter)
//the filter logic
def filteredKeys = params.findAll{k,v->
//if value is collection then lookup if any element instance of our filter class
if (v instanceof Collection)return v.find{filterClazz.isInstance(it)}
//otherwise (not collection) just check if value is filter class
return filterClazz.isInstance(v);
}.collect{it.getKey()} //collect only key names
println filteredKeys

Elasticsearch sort option not supported

I'm using elastic search in Rails. I am trying to sort a list of customers by their total dollars spent descending. This is my ruby code:
query = {
bool: {
filter: {
term: { store_id: store.id } # Limits customers by current store
}
}
}
sort = {
sort: { "total_spent": { order: "desc" }}
}
response = Contact.search(query: query, sort: sort)
This returns with an error of sort option [total_spent] not supported I've tried with other fields to make sure it wasn't just something wrong with the total_spent field. Thanks.
I'm not really sure, but I think this may be related to incorrect usage of the ES::DSL.
What happens when you try this:
query = {
bool: {
filter: {
term: { store_id: store.id } # Limits customers by current store
}
}
}
sort = {
sort: [{ "total_spent": { order: "desc" }}] #https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-sort.html
}
response = Contact.search(query, sort)
We can sort specific to the field, refer https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-sort.html.
so we can use like,
query = {
bool: {
filter: {
term: { store_id: store.id } # Limits customers by current store
}
},
sort: { total_spent: { order: :desc }}
}
response = Contact.search(query)

Grails 2.5.0 - metaParams on Set?

I have the following class:
class User {
...
static hasMany = [data: MyData]
...
}
I would like to get user.data on a User object but filter the returned list using metaParams like in findAllBy (https://grails.github.io/grails-doc/latest/ref/Domain%20Classes/findAllBy.html).
Is this possible?
With a criteria query you can do something like this:
def id = /* some User.id here */
// http://grails.github.io/grails-doc/2.1.0/ref/Domain%20Classes/createCriteria.html
def data = User.createCriteria().list(max: 10, offset: 100) {
projections {
property 'data'
}
eq 'id', id
order 'something', 'desc'
}
If you end up with duplicate MyData instances, try using HQL instead. Like this:
// https://grails.github.io/grails-doc/latest/ref/Domain%20Classes/executeQuery.html
User.executeQuery 'select distinct u.data from User as u where u.id = :id', [id: id, max: 10, offset: 5]

I want to add pagination in a criteria returned value

params.max = Math.min(params.max ? params.int('max') : 2, 100)
orders=OrderInfo.createCriteria().listDistinct()
For pagination, we need to pass the params to list eg. Post.list(params). How do I pass it here? I tried but gives an error.
We also require total number which I get.
But I am not able to set params in
orders=OrderInfo.createCriteria().listDistinct()
Pls suggest the correct code
If you pass the params as first parameter of the list method, you get an PagedResultList which has the method getTotalCount(). With this you could get total number of instances.
params.max = Math.min(params.max?.toInteger() ?: 25, 100)
params.offset = params.offset ? params.offset.toInteger() : 0
def orderInfoCriteria = OrderInfo.createCriteria()
def results = orderInfoCriteria.list(params) { // your criteria code ... }
log.debug "Getting ${results.size()} order infos of ${results.totalCount}"
Read the docs for more information about critera.
Grails Criteria Query and pagination params
params.max = params?.max as Integer ?: 10
params.page = params?.page as Integer ?: 1
params.offset = (params.page - 1) * params.max
params.sort = params?.sort ?: "email"
params.order = params?.order ?: "asc"
params.filter = params?.filter ?: ""
params.packet = params?.packet ?: ""
def members = Member.createCriteria().list(params)
{
or
{
if(params.filter != ""){
ilike("firstName", "%" + params.filter + "%")
ilike("lastName", "%" + params.filter + "%")
ilike("email", "%" + params.filter + "%")
try {
params.filter as Long
eq("citizenId" , params.filter.toLong())
}catch (e) {
}
ilike("mobile", "%" + params.filter + "%")
}
}
}
def dataMembers = [:]
dataMembers.data = members
dataMembers.totalRecord = members.totalCount
render dataMembers as JSON
Output
{
"data": [
{
"id":1,
"firstName":name
},
{
"id":2,
"firstName":name
}
],
"totalRecord":5
}

Resources