Grails Sorting Giving me hard times - sorting

Sort of new to grails! I am currently working on grails 2.3.11 and I can't see why the following code is not working as intended!
def listCommodity() {
List<Commodity> commodities;
if (params.searchBox) {
commodities = Commodity.list().findAll {
it.name.toLowerCase().contains("${params.searchBox.toLowerCase()}") ||
it.type.name.toLowerCase().contains("${params.searchBox.toLowerCase()}") ||
(it.type.parent ? it.type.parent.name.toLowerCase().contains("${params.searchBox.toLowerCase()}") : false)
}
} else {
commodities = Commodity.list()
}
commodities?.sort { one, two ->
if ("decs" == params?.order) {
return two.name <=> one.name
} else {
return one.name <=> two.name
}
}
def max = Math.min((params.max ?: 10) as Long, 100)
def offset = Math.min((params.offset ?: 0) as Long, commodities.size() - 1)
if (!commodities) {
flash.message = "No Items found Here!"
return [commodities: [], commoditiesCount: 0]
} else {
return [commodities: commodities[offset..Math.min(offset + max, commodities.size() - 1)], commoditiesCount: commodities.size(), searchBoxText: params.searchBox ?: '']
}
}
view:
....
<tr>
<g:sortableColumn params="${[searchBox:searchBoxText]}" property="name" title="${message(code: 'commodity.commodity.name.label', default: 'Name')}" />
</tr>
....
<% println commodities //here it prints the items in ascending %>
<g:each in="${commodities}" status="i" var="com">
<tr class="${(i % 2) == 0 ? 'even' : 'odd'}">
<td>
${com?.getName(lang)}
</td>
</tr>
</g:each>
....
this test passes:
given:
mockDomain(CommodityType,[[name: "Cereals"],[name: "Group", parent: new CommodityType(name: 'Corea')]])
mockDomain(Commodity,
[[name:"Kea", type:CommodityType.findByName("Cereals")],
[name:"Shiro", type:CommodityType.findByName("Cereals")],
[name:"Other with ea", type:new CommodityType(name: "Grass")],
[name:"Barely", type:CommodityType.findByName("Group")],
[name:"Teff",type:CommodityType.findByName("Cereals")]])
when:
params.order = "decs"
params.searchBox = "ea"
def models = controller.listCommodity()
then:
5 == models.commodities.size()
"Barely" == models.commodities[-1].name
"Teff" == models.commodities[0].name
"ea" == models.searchBoxText
when:
params.order = "asc"
params.searchBox = "ea"
def models2 = controller.listCommodity()
then:
5 == models2.commodities.size()
"Barely" == models2.commodities[0].name
"Teff" == models2.commodities[-1].name
"ea" == models2.searchBoxText
but when i test it on the browser! The sorting doesn't do anything! The i did a println on the view and the list is never sorted! What am i doing wrong?

Two things to check :
use sort(boolean, closure) with true in the 1st argument to sort the list itself, otherwise a copy is created
the standard parameter is "desc" not "decs"
Good luck!

Related

Elasticsearch painless sorting null_pointer_error

I'm trying to create a sorting script with painless, filtering nested documents.
The reason I'm doing this with a script, is because I need to emulate a COALESCE statement.
My documents have titles stored like:
{
title: [
{
type: MainTitle,
value: [
{
language: eng,
label: The title
},
{
language: ger,
label: Das title
}
]
},
{
type: AvailabilityTitle,
value: [
{
language: eng,
label: New thing!
}
]
}
]
}
title and title.value are nested documents.
I want to sort documents primarily by their english MainTitle and by their german MainTitle only if no english MainTitle exists - even if the german title gave a higher score.
I'm trying to simply sort by the english MainTitle first to try it out and this is the script:
def source = params._source;
def titles = source.title;
if (titles != null && titles.length > 0) {
for(int i=0; i < titles.length; i++) {
def t = titles[i];
if (t.type == 'MainTitle') {
def values = t.value;
if (values != null && values.length > 0) {
for (int j = 0; j < values.length; j++) {
def v = values[j];
if (v.language == 'eng') {
return v.label;
}
}
}
}
}
}
return \"\";
For some reason I'm getting a null_pointer_exception
"script_stack": [
"if (values != null && values.length > 0) { ",
" ^---- HERE"
],
I don't get how values can be null at that point since I'm specifically checking for null just before it.
The null_pointer_exception is thrown, not because values is null, but because values does not have a method/function called length. That is because for some reason values is an ArrayList even though titles earlier is an Array. Apparently they both have the method/function size() so I can just use that.
So this works:
def source = params._source;
def titles = source.title;
if (titles != null && titles.size() > 0) {
for(int i=0; i < titles.size(); i++) {
def t = titles[i];
if (t.type == 'MainTitle') {
def values = t.value;
if (values != null && values.size() > 0) {
for (int j = 0; j < values.size(); j++) {
def v = values[j];
if (v != null && v.language == 'fin') {
return v.label;
}
}
}
}
}
}
return '';

Filter multiple values in Swift

I know that Filter and contains in Swift are very powerful and it has made many of my works easy. However, I'm stranded in a situation where I have to filter/verify a set of different values from an array of Model.
Let's assume I have a model like below
struct Person {
var name: String
var ID: String
}
And I have an array of models like below:
[
{
sku = "123"
attributes = [
{
name:"Victor"
ID:"250"
},
{
name:"Shaw"
ID:"252"
}
]
},
{
sku = "123"
attributes = [
{
name:"John"
ID:"222"
},
{
name:"Nixon"
ID:"333"
}
]
}
]
Now I would like to filter the sku by multiple IDs inside attributes . For example, if I need to filter skus which has ID:250 and ID:252 I need something like this to achieve it.
personModelArray.forEach { person in
person.attributes.contains(where: { $0.ID == 250 && $0.ID == 252 })
}
OR
personModelArray.forEach { person in
person.attributes.filter { $0.ID == 250 && $0.ID == 252 }
}
What I want is a condition like to to verify that the attributes array has both the values.
The condition $0.ID == 250 && $0.ID == 252 is ALWAYS false! How one storage could have two different values at the same moment?
Look at this simple example
struct Item {
let a: Int
let b: String
}
let arr = [Item(a: 0, b: "zero"),
Item(a: 1, b: "one"),
Item(a: 2, b: "two"),
Item(a: 4, b: "four")]
To filter all items, where a == 1 OR a == 4
let arr0 = arr.filter { item in
item.a == 1 ||
item.a == 4
}
or, if You prefer $ parameter notation
let arr1 = arr.filter { $0.a == 1 || $0.a == 4 }
eventually,
let arr2 = arr.filter { item in
[1, 4].contains(item.a)
}
let arr3 = arr.filter { [1, 4].contains($0.a) }

Aggregating sequence of connected events

Lets say I have events like this in my log
{type:"approval_revokation", approval_id=22}
{type:"approval", request_id=12, approval_id=22}
{type:"control3", request_id=12}
{type:"control2", request_id=12}
{type:"control1", request_id=12}
{type:"request", request_id=12 requesting_user="user1"}
{type:"registration", userid="user1"}
I would like to do a search that aggregates one bucket for each approval_id containing all events connected to it as above. As you see there is not a single id field that can be used throughout the events, but they are all connected in a chain.
The reason I would like this is to feed this into a anomaly detector to verify things like that all controls where executed and validate registration event for a eventual approval.
Can this be done using aggregation or are there any other suggestion?
If there's no single unique "glue" parameter to tie these events together, I'm afraid the only choice is a brute-force map-reduce iterator on all the docs in the index.
After ingesting the above events:
POST _bulk
{"index":{"_index":"events","_type":"_doc"}}
{"type":"approval_revokation","approval_id":22}
{"index":{"_index":"events","_type":"_doc"}}
{"type":"approval","request_id":12,"approval_id":22}
{"index":{"_index":"events","_type":"_doc"}}
{"type":"control3","request_id":12}
{"index":{"_index":"events","_type":"_doc"}}
{"type":"control2","request_id":12}
{"index":{"_index":"events","_type":"_doc"}}
{"type":"control1","request_id":12}
{"index":{"_index":"events","_type":"_doc"}}
{"type":"request","request_id":12,"requesting_user":"user1"}
{"index":{"_index":"events","_type":"_doc"}}
{"type":"registration","userid":"user1"}
we can link them together like so:
POST events/_search
{
"size": 0,
"aggs": {
"log_groups": {
"scripted_metric": {
"init_script": "state.groups = [];",
"map_script": """
int fetchIndex(List groups, def key, def value, def backup_key) {
if (key == null || value == null) {
// nothing to search
return -1
}
return IntStream.range(0, groups.size())
.filter(i -> groups.get(i)['docs']
.stream()
.anyMatch(_doc -> _doc.get(key) == value
|| (backup_key != null
&& _doc.get(backup_key) == value)))
.findFirst()
.orElse(-1);
}
def approval_id = doc['approval_id'].size() != 0
? doc['approval_id'].value
: null;
def request_id = doc['request_id'].size() != 0
? doc['request_id'].value
: null;
def requesting_user = doc['requesting_user.keyword'].size() != 0
? doc['requesting_user.keyword'].value
: null;
def userid = doc['userid.keyword'].size() != 0
? doc['userid.keyword'].value
: null;
HashMap valueMap = ['approval_id':approval_id,
'request_id':request_id,
'requesting_user':requesting_user,
'userid':userid];
def found = false;
for (def entry : valueMap.entrySet()) {
def field = entry.getKey();
def value = entry.getValue();
def backup_key = field == 'userid'
? 'requesting_user'
: field == 'requesting_user'
? 'userid'
: null;
def found_index = fetchIndex(state.groups, field, value, backup_key);
if (found_index != -1) {
state.groups[found_index]['docs'].add(params._source);
if (approval_id != null) {
state.groups[found_index]['approval_id'] = approval_id;
}
found = true;
break;
}
}
if (!found) {
HashMap nextInLine = ['docs': [params._source]];
if (approval_id != null) {
nextInLine['approval_id'] = approval_id;
}
state.groups.add(nextInLine);
}
""",
"combine_script": "return state",
"reduce_script": "return states"
}
}
}
}
returning the grouped events + the inferred approval_id:
"aggregations" : {
"log_groups" : {
"value" : [
{
"groups" : [
{
"docs" : [
{...}, {...}, {...}, {...}, {...}, {...}, {...}
],
"approval_id" : 22
},
{ ... }
]
}
]
}
}
Keep in mind that such scripts are going to be quite slow, esp. when run on large numbers of events.

GRAILS - GORM : DuplicateKeyException during saving a new object

I use GORM to back occurrences in a database, from an excel file.
new ExcelBuilder(excelFile.inputStream).eachLine([labels: true, sheet: 0]) {
if (cell(0)) {
def nameA = cell(0)
def nameB = cell(1)
def a = Chapitre.findByNom(nameA)
def code = cell(2)
def designation = cell(3)
if (code == null || nameA == null || nameB == null) {
flash.messages << "error"
} else if (!Chapitre.findByNom(nameA)) {
flash.messages << "error"
} else if ( Rubrique.where{nom == nameB && chapitre == a}.list().size() == 0) {
flash.messages << "error"
} else if(Object.where{rubrique == Rubrique.findByNom(nameB) && c == code && d == designation}.count() > 0){
flash.messages << "error"
} else {
def b = Rubrique.findByNom(nameB)
def isNew = false;
Object.withNewSession {session2->
def object = Object.findOrCreateByCode(code)
if(object.designation == null)
isNew = true;
object.rubrique = b
object.d= (designation == null)?"":designation
// try {
rowCount += object.save()? 1 : 0
// } catch(ValidationException) {
// if(isNew)
// rowCount++;
// log.info("ErreuRRRRRRRRrrrRRrrRrRRrrrrRrrrRrrrRrrrr")
// }
}
}
}
currentLine++
}
flash.messages << "${rowCount} ligne create or update"
An update will break any worries, the course of the lines of file continue and database recording is effective.
However when it comes to inserting a new object, I get an Exception:
org.springframework.dao.DuplicateKeyException: a different object with the same identifier value was already associated with the session:[fen.NuisanceType#2202];
nested exception is org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session
The registration of the object in question is effective , but the error raised off the path of the file.
When i uncommented the try and catch I bypasses the error and so all my copies of each file are created in the database .
I thus found a way around my worries, but I do not find it very clean and i come to you to try to understand my problem.
Without further information hard to give any clear answers. Is this code back in a service?(very much doubt it since it has flash.message pointing to controller doing all of it.) Try making it into a service and transactional then maybe you could look at removing withNewTransaction call.
You can read more about error created here:
Grails - DuplicateKeyException
Review comment:
"Well, that problem occurs when you are initializing a class new ClassD with an id or unique property manually, when there is another already in the session. So, you should try to get that entity first (that's what findOrCreateWhere does, but if you use an id you need to use get) and then use the instance found or create a new one for the update"
Hibernate Error: a different object with the same identifier value was already associated with the session
You code tidied up and running from service: (issues may go away) since I have also cleaned up the duplicated finds you were doing:
class TestService {
static transactional=true
def saveRecord() {
def results=[]
new ExcelBuilder(excelFile.inputStream).eachLine([labels: true, sheet: 0]) {
if (cell(0)) {
def nameA = cell(0)
def nameB = cell(1)
def code = cell(2)
def designation = cell(3)
def a = Chapitre.findByNom(nameA)
def b = Rubrique.where{nom == nameB && chapitre == a}
def c = Object.where{rubrique == b && c == code && d == designation}
if (!code||!nameA||!nameB||!a||!b||!c) {
results << "Error saving ${nameA} ${nameB} ${code}"
} else {
//boolean isNew = false
def object = Object.findOrSaveWhere(code:code)
if(object) {
if (!object.designation) {
rowCount++
results << "Record ${object} has no designation ? new Record?"
}
object.rubrique = b
object.d = designation ?: ''
object.save()
results << "Record ${object.id} is saved"
} else {
/*
* Could not save or find code:code now create a new object:
* object = new Object(code:code, rubrique:rubrique: d: designation ?: '').save()
*
*/
}
}
}
currentLine++
}
results << "${rowCount} ligne create or update"
return results
}
}

grails ajax onload and oncomplete

can anyone give me sample coding that using grails ajax onload and oncomplete functions on following reader action? i want show a spinner icon while this action is onload and redirect to the list page while action is oncomplete..
def reader(){
def list = []
def dir = new File("C:/Users/User/Desktop/Summarize_20141212/HR_FILE")
dir.eachFileRecurse(FileType.FILES) { file ->
list << file
}
println list
list.each {
File file = new File(it.path)
def sql = groovy.sql.Sql.newInstance("jdbc:postgresql://localhost:5432/new",
'postgres', 'sa', "org.postgresql.Driver")
def lincoln = 0
file.eachLine() { line ->
if (line.trim().size() == 0) {
return null
} else {
def field = []
def tokens = line.split(',(?=([^\"]*\"[^\"]*\")*[^\"]*$)')
file.name.lastIndexOf('.').with { it != -1 ? file.name[0..<it] : file.name }
lincoln++
field.push(file.name)
for (String t : tokens) {
field.push(t)
}
while (field.size() < 10) {
field.push("")
}
if (lincoln > 1) {
sql.execute('insert into read_hr(version,col01,col02,col03,col04,col05,col06,col07,col08,col09,col10)' +
'VALUES (0,?,?,?,?,?,?,?,?,?,?)', field)
System.out.println(field);
}
}
}
}
redirect (action:"list")
}
These link will useful to you .
http://www.javacodegeeks.com/2013/05/grails-ajax-examples.html
http://javadeveloper.asia/grails-ajax-tutorial-remotelink-tag

Resources