Grails build list of usernames from database - grails

I am trying to build an alphabetically sorted list of user names from my User objects in the database. Im finding that all the different ways of list() only returns the entire User objects. I just need their usernames which is a property of each User. I need to feed this list to a g:select pull down list on my gsp. Can't seem to put the code together. I am using Mongodb but that shouldn't really matter I know. Here's my algorithm.
Iterate through the user collection and grab the property username on each.
collect all usernames into list then alphabetically sort it
feed it to the g:select list
maybe something like
list userList = User.list()
list usernameList
usernameList << a groovy loop to collect it.username(s)
and then alphabetically sort usernameList then feed it to g:select.

You can (and should) create custom query, just create a hql query and then use the method executeQuery:
http://grails.org/doc/2.3.7/ref/Domain%20Classes/executeQuery.html
User.executeQuery("SELECT username FROM User u order by u.username asc")

Ok here is a shorter way userlist = User.list().collect{it.username}.sort(java.text.Collator.instance)

here is my solution
def usersList = User.list().username.sort()

Here's one possible way to do it:
userlist = User.list()
def userlist2 = []
userlist.each { userlist2 << it.username }
userlist2.sort()
userlist = userlist2
Now userlist is ready as you need it to be fed into g:select

Related

How to bulid a criteria query to get the data of my domain

I know that have to be really easy, but I'm new in grails and I don't find any clear answer. That I want to do is read and get with a criteria query the data that I have in my domain do a search for each parameter.
This is my domain Person:
String name
String surname
String address
String village
String country
This is that I'm trying to do:
def getData = Person.createCriteria()
I can see in the log that I have an object (com.mypackagename.Person: 1.), but not the data that I have in the database. example (myname, mysurname, myaddress, myvillage, mycountry)
I only have one row of data in my database and I want to get the data of every column and do a search for each parameter
Thanks in advance.
Let me show you the code first, then I'll explain it:
class SomeController {
def search() {
def people = Person.withCriteria {
params
.findAll { name, value -> name in ['name', 'surname', 'address', 'village', 'country'] }
.each { name, value -> eq(name, value) }
}
// Do as you please with 'people'; a list of Person instances.
}
}
Ok, so let's say you have a controller method (ex. search()) which receives the query parameters from the user. The parameters would be in the params Map. For example, if the user searches for the name John and the country USA, params would look like this: [name: 'John', country: 'USA']. Even though there are other search parameters available, we won't use them because the user did not specify them.
Within the criteria query, first search for the param key/value pairs which you care about; the searchable properties of Person. Then, for each of those pairs call eq(String propertyName, Object value) to set up the query criteria (the WHERE clause).
Using the example data, Hibernate will generate SQL that looks something like this:
SELECT name, surname, address, village, country
FROM person
WHERE name = 'john' AND country = 'USA'
And that's it!
Note: You will see the same output in the log (ex. com.mypackagename.Person: 1). That's because you're logging personInstance.toString(). So if you want the log entry to look differently, you'll need to override Person.toString() A very easy way to remedy this is to use Groovy's #ToString AST.
For more about creating criteria queries, take a look at my series of articles. I cover criteria queries using SQL terminology.
Try to use:
def persons = Person.createCriteria().list{}
or if you want just one result:
def persons = Person.createCriteria().list {
maxResults 1
}
Moreover please read about using Criteria and Querying with GORM

Rails/Mongoid best way to save sortable ordered list

I've got a sortable list of players pulled from my db. Users can rank them in order of their preference.
What's the best way to store that order in the db associated with each player's preference and retrieve player stats back in that same order?
Right now I'm retrieving by #playersdraftlist = #draftlist.map { |id| Player.find(id) }, but this hits the db many times.
So, currently, I have a User model and a Draft model. The draft only has an associated user_id.
1) Would it be better to just store the draftees as a user field instead of a separate model?
2) Is there a better way to store a list like this when I need to retain dupes and order?
Structure:
PlayerDraft model has an associated user_id:
draftees: [
"52f4fd9f52e39bc0c15674ea", #Peyton
"52f4fd9f52e39bc0c15674eb", #Tom
"52f4fd9f52e39bc0c15674ea" #Peyton
],
user_id: "52f581096b657612fe020000"
#draftees = Draft.find(user_id = current_user._id).first.draftees will return the draftees array.
Calling Player.find(#draftees) will remove the duplicates and order by _id.
Edit
Here is my poor solution:
def index
#players = Player.all
if current_user.draft_list.draftees == [""]
#playersdraftlist = ""
else
# Get all picks for current user
#picks = current_user.draft_list.draftees
#draft = Player.find(#picks)
#playersdraftlist = #picks.map { |id| Player.find(id) }
end
end
The way to do this is to use the identity map in mongoid.
There are more details on this here: http://mongoid.org/en/mongoid/docs/identity_map.html
But the short and simple way to do this is in your mongoid.yml set the following property:
identity_map_enabled: true
Then search for the following: Player.find(#draftees)
And this will return your draftees in the order of the array that you passed in. One caveat is that it won't return duplicates so your #draftees array above if used would return only two values (the order is based on the first appearance of the id, so it will return the player with id "52f4fd9f52e39bc0c15674ea" first and then the player with id "52f4fd9f52e39bc0c15674eb"). So you will have to recreate the duplicates via some sort of abstraction.
Here is one possible way to do this, and it was inspired by a comment posted by #muistooshort below:
In your User class add the following function
def get_draftee_list
players = Player.find(self.draftees).each_with_object({}) { |p, h| h[p.id] = p }
return self.draftees.map { |id| players[Moped::BSON::ObjectId.from_string(id)] }
end
Note: This was tested on Mongoid 3
This should solve your problem since each call to raw_data.find(id) is searching the result set from your the initial query which is stored in memory and not making another query to the db

Not retrieving all objects using Doctrine 2 querybuilder

I've made a query using querybuilder. It look likes:
//Create a Querybuilder
$qb = $this->_em->createQueryBuilder();
//Foreach entity, check if it's a join and leftjoin it.
//If there's no join, make it the select
foreach($config['entities'] as $name => $entity)
{
//add new alias(ses) to select statement
$qb->addSelect($entity['alias']);
if(!isset($entity['join'])){
$qb->from($entity['path'], $entity['alias']);
} else {
$qb->leftJoin($entity['join'], $entity['alias']);
}
}
->orWhere(':test IS NULL')
->setParameter('test', 'User\Entity\Address');
//Make the query
$query = $qb->getQuery();
//Return the result
return $query->getResult();
I've made my select and left join dynamically with a config file. So people can make own joins. But when i have (for example) users and addresses. It shows only users WITH addresses. Users without addresses are not show. When i've no join, all users show up. Has somebody an idea about it? I read something like i've to set a where clause and do something like:
->orWhere(':test IS NULL')
->setParameter('test', 'User\Entity\Address');
It doesn't work. How can i have joins AND show all the users also WITHOUT addresses?
Grtz
I've a problem with my where clause. It had a "like" in it, where he wants to like the "street" (from addresses), to something. But when users didn't had a address, he can't like and so he don't show the whole user.

findBy multiple attributes (findAllWhere)

I have an object from which I must filter certain attributes, some of which could also be "null". I have a Filter object and a Product object.
In the Filter object I have certain attributes reflecting the Product object which can be filled out or be left blank. Here a shortened view on the classes.
Product: String name, Boolean isEmpty, ...., belongsTo [Producer, Distributor]...
Filter: Boolean isEmpty, ... belongsTo [Producer, Distributor]...
With this filter I can search for all Products having certain attributes (empty, Producer, Distributor).
I have an export functionality where I can select the filter and it outputs the information based on that selection for the Products.
As all of these attributes can be null, but also contain a value, I first of thought to construct an own search query (combining strings etc) to construct an SQL-string and then using Product.findAll(string_query, string_params). But as this is quite tedious, I changed it now to someting like this:
if(filter.producer)
prods = Product.findAllWhere(producer:filter.producer)
if(filter.distributor)
prods = prods.findAll {it.distributor == filter.distributor}
if(filter.isEmpty!=null) //as it could be NULL but also false/true
prods = prods.findAll {it.isEmpty == filter.isEmpty}
But this becomes quite a larger task if I have 10-15 attributes to be filtered. I'm not very experienced with Grails or Groovy but I guess this can be solved easier, right?
I believe you'll find Grails Criteria queries to be a very nice way to accomplish tasks like this. See:
http://grails.org/doc/latest/guide/single.html#criteria
http://viaboxxsystems.de/the-grails-hibernatecriteriabuilder
Your sample might look something like this when expressed as a criteria query:
def prods = Product.createCriteria().list {
if(filter.producer) eq("producer", filter.producer)
if(filter.distributor) eq("distributor", filter.distributor)
if(filter.isEmpty != null) eq("isEmpty", filter.isEmpty)
}

How Do I Query In Groovier Way?

I have User class which has a field type, which is in turn a list.
So type might look like : ["a","b"]
I have a another list, say search like ["c","b"] (this is pre-defined)
Now what I want is to search all my User instances such that I can find users type matching with any one of the elements from search.
I came up with a partial solution :
def newQ = User.findAllByUsernameIsNotNull()
newQ.each { eachIndex ->
query = eachIndex.type
result = query.findAll { it == "c" }
if(result.size() > 0 )
{
ans << eachIndex.username
}
}
The above code works, ans list have all User which satisfy my condition. But you can clearly see that in query.findAll line, I'm doing a search only for one element from search. I want to perform search operation for all search element against query(which is User's type field).
How can I achieve that? Apart from my solution are there any easy way to do that?
Thanks in advance.
You could do something like:
def ans = []
search.each{s->
ans += User.findAll("from User u where u.username is not null and ? in elements(u.type)",[s])
}
I can't think of a way to do it in a single query
User.withCriteria {
isNotNull("username")
'in' ("type", search)
}
When searching you want to go to the database as few times as possible since those are usually the most expensive operations. If the User.withCriteria {..} works I'd use that (I'm not as familiar with .withCriteria{}). This would work as well if you still wanted to use the dynamic finders since mockDomain doesn't work with HSQL (again not sure if .withCriteria{} works with mockDomain).
def search = ["c", "b"]
def users = User.findAllByUsernameIsNotNull()
users = users.findAll {it.type.intersect(search)}

Resources