I have a rails app with mongoid5.
In my Project model has an attribute like this:
permissions : {
"18748343" : 2,
"23453744" : 3,
"23453444" : 1
}
and an array like this
role_ids = ["123456", "23453744"]
I want to query on projects that has one of the role_ids members as key in their permissions attribute and value of that key is more than 1.
How can I make this query with mongoid criteria?
If you are using Mongoid::Attributes::Dynamic, mongoid5 will allow you to query like this:
Project.where('permissions.123456'.ne => nil)
This is because in mongo, permissions is document, with keys
Related
I'm new to Rails and I'm using Google Translate to post.
I currently have this filter, however, it filters only one item from public_sphere, how do I make it a multiple filter, in this case, the user can select more than one option from public_sphere.
scope :filter_public_sphere, -> (params) {
params[:public_sphere].present? ?
where(
"public_sphere = ?",
AtaPublic.public_spheres[params[:public_sphere]]
)
:
all
}
In this case, the API must receive an array instead of a value. For that, what would my filter look like?
Arel should do the work for you. If you have a where clause in the form where(attribute: [array of attribute values]) it will generate an IN clause for the SQL
scope :filter_public_sphere, -> (params) {
params[:public_sphere].present? ?
where(
public_sphere: AtaPublic.public_spheres[params[:public_sphere]]
)
:
all
}
Assuming AtaPublic.public_spheres[params[:public_sphere]] returns an array of "public_sphere" identifiers.
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
I have a following domain class:
class User {
static hasMany = [roles:String]
}
I would like to find every user which has role ROLE_ADMIN. Is there any possibility to do that with dynamic finders? user.findAllByRoles('ROLE_ADMIN') seems to give me an error.
UPDATE: it is quite easy to query association where Class A has a list of class B instances and both A and B are domain classes. But here class A is a domain class and class B is a simple Java string.
The code for querying association containing list of another domain objects would look like this:
`User.findAll { roles { role_name=='ROLE_ADMIN' } }`
What i am looking for is a way to specify the value of a String, for example:
`User.findAll { roles {THIS_VALUE=='ROLE_ADMIN' }}`
UPDATE 2: as far as i have found it is not possible to use criteria with collections of primitive types. It is possible to use HQL though:
User.findAll("from User a where :roles in elements(roles)",[roles:'ROLE_ADMIN'])
However it is not as usefull as a findAll or where query. I cannot chain findAll methods so defining other methods that for example: get ROLE_ADMIN users with username like 'xxx' requires rewriting whole HQL query. Maybe it is possible to express above HQL condition in form of a where expression?
Maybe you can do something like:
if you have already a user list (userList)
def list = userList.findAll { user -> user.roles =~ 'ROLE_ADMIN' }
Hope this help!
I have the same problem How to find records by value in their association property via DetachedCriteria
I made some investigation and, as I found, it's impossible.
The GORM DSL itself doesn't have any method to check that value contains in association.
It conains oly that criterias that are in SQL: AND, OR, IN.
But! You can join association as table in criteria Querying by Association Redux
I'm trying a query in Grails 1.2.1, find all products by tenant type.
My solution works but is very inefficient, first I retrieve all products and then find all matching results for the given tenant.
I found a related bug in JIRA: Enum as collection
class Product {
Set<TenantType> tenants
static hasMany = [tenants: TenantType]
}
enum TenantType {
BICYCLE,
MOTORCYCLE
}
def tenant = TenantType.BICYCLE
Product.list().findAll { product -> tenant in product.tenants }
Is there a more efficient way of querying for this data?
A similar question was asked here and as pointed out in the answer, it looks like Hibernate doesn't support criteria queries over collections of value types like enums. One option is to use an hql query instead:
Product.executeQuery('from Product p inner join p.tenants tenants
where tenants = :tenant', [tenant: TenantType.BICYCLE])
Can be executed without join:
Product.executeQuery('from Product where :tenant in elements(tenants)', [tenant: TenantType.BICYCLE])
Use named query in Product class something like
findByTenantType { tenantType->
tenants{ eq 'value', tenantType}
}
And then access this named query like this -
def product = Product .findByTenantType(TenantType.BICYCLE).get()
see similar blog - http://www.grailsbrains.com/search-parent-through-child-in-aggregation-relationship/
I have a domain similar to this in Grails
class User {
static mapWith = "mongo"
ObjectId id
String name
String address
Integer age
}
I am building a search front-end in Grails to query a MongoDb database using the MongoDb plugin. Searching can be done on any of the fields in the database and any field that is not set by the user must be not be used in the query. I.e. no fields shall be compared to null. For example leaving all the fields empty returns all Users but searching for name returns only documents which matches on name.
Initially my queries was simple and I used User.find(new User(params)); in my controller which worked fine. Now I need to be able to also query integer fields using intervals, greater than and less than. I've looked at withCriteria() and to build the query depending on what fields the user have set but so far I've been unsuccessful.
TL;DR
How can I do a query where I don't know which fields the user want to include in the query?
I solved it by using withCriteria() like this:
def c = User.createCriteria()
def users = c.list {
if(params.name)
eq('name', params.name)
if(params.address)
eq('address', params.address)
if(params.age_gt?.isInteger())
gt('age', params.age_gt as Integer)
if(params.age_lt?.isInteger())
lt('age', params.age_lt as Integer)
}