groovy query is being generated with "and' rather than "or" - grails

I am trying to run a query to find entries based on 3 fields with "or" conditions. This is my query:
def results = Person.createCriteria().list(params) {
eq "skillset.id", original.skillset.id
or { eq "primarySkill.id", original.primarySkill.id }
or { eq "jobRole.id", original.jobRole.id }
not { eq "id", original.id }
order "name", "asc"
}
In the person object, the 3 fields that I care about: skillset, primarySkill, and jobRole, are instances to another object. I want to find any person where any of those fields match, except for the original person. However, the hibernate query appears to be making an "and" query rather than an "or" query. I could type out the SQL myself, but I'd like to learn how to do it the groovy way.
And this is the query generated by hibernate
select this_.id as id5_0_,
this_.version as version5_0_,
this_.account_id as account3_5_0_,
this_.band as band5_0_, t
his_.end_date as end5_5_0_,
this_.job_role_id as job6_5_0_,
this_.name as name5_0_,
this_.primary_skill_id as primary8_5_0_,
this_.professional_market_place as professi9_5_0_,
this_.project_delivery_manager_id as project10_5_0_,
this_.project_manager_id as project11_5_0_,
this_.project_name as project12_5_0_,
this_.rate as rate5_0_,
this_.resource_deployment_manager_id as resource14_5_0_,
this_.skillset_id as skillset15_5_0_,
this_.start_date as start16_5_0_,
this_.work_location as work17_5_0_
from person this_ where this_.skillset_id=?
and (this_.primary_skill_id=?)
and (this_.job_role_id=?)
order by this_.name asc limit ?

I believe it should be
def results = Person.createCriteria().list(params) {
or {
eq "skillset.id", original.skillset.id
eq "primarySkill.id", original.primarySkill.id
eq "jobRole.id", original.jobRole.id
}
not { eq "id", original.id }
order "name", "asc"
}

Related

How do I convert this SQL query into a Grails or GORM query

How can I write the below SQL query in Grails or GORM?
select email, count(*) as c FROM orders GROUP BY email
Use Projections!
def result = Orders.createCriteria().list() {
projections {
groupProperty("email")
count()
}
order("email", "asc")
}
Edit: Or HQL, I guess...
def list = Orders.executeQuery("select email, count(*) from Orders group by email")
list.each { item ->
def email = item[0]
def count = item[1]
println "There are ${count} people with the e-mail address of ${email}"
}
(I just eyeballed that, but I think it's about right, might take some tweaking)

Scope Order by Count with Conditions Rails

I have a model Category that has_many Pendencies. I would like to create a scope that order the categories by the amount of Pendencies that has active = true without excluding active = false.
What I have so far is:
scope :order_by_pendencies, -> { left_joins(:pendencies).group(:id).order('COUNT(pendencies.id) DESC')}
This will order it by number of pendencies, but I want to order by pendencies that has active = true.
Another try was:
scope :order_by_pendencies, -> { left_joins(:pendencies).group(:id).where('pendencies.active = ?', true).order('COUNT(pendencies.id) DESC')}
This will order by number of pendencies that has pendencies.active = true, but will exclude the pendencies.active = false.
Thank you for your help.
I guess you want to sort by the amount of active pendencies without ignoring categories that have no active pendencies.
That would be something like:
scope :order_by_pendencies, -> {
active_count_q = Pendency.
group(:category_id).
where(active: true).
select(:category_id, "COUNT(*) AS count")
joins("LEFT JOIN (#{active_count_q.to_sql}) AS ac ON ac.category_id = id").
order("ac.count DESC")
}
The equivalent SQL query:
SELECT *, ac.count
FROM categories
LEFT JOIN (
SELECT category_id, COUNT(*) AS count
FROM pendencies
GROUP BY category_id
WHERE active = true
) AS ac ON ac.category_id = id
ORDER BY ac.count DESC
Note that if there are no active pendencies for a category, the count will be null and will be added to the end of the list.
A similar subquery could be added to sort additionally by the total amount of pendencies...
C# answer as requested:
method() {
....OrderBy((category) => category.Count(pendencies.Where((pendency) => pendency.Active))
}
Or in straight SQL:
SELECT category.id, ..., ActivePendnecies
FROM (SELECT category.id, ..., count(pendency) ActivePendnecies
FROM category
LEFT JOIN pendency ON category.id = pendency.id AND pendnecy.Active = 1
GROUP BY category.id, ...) P
ORDER BY ActivePendnecies;
We have to output ActivePendnecies in SQL even if the code will throw it out because otherwise the optimizer is within its rights to throw out the ORDER BY.
For now I developed the following (it's working, but I believe that it's not the best way):
scope :order_by_pendencies, -> { scoped = Category.left_joins(:pendencies)
.group(:id)
.order('COUNT(pendencies.id) DESC')
.where('pendencies.active = ?', true)
all = Category.all
(scoped + all).uniq}

select joins and group by in codeigniter

In Codeigniter3, I have the following select join model:
public function get_post()
{
$q = $this->db->select('posts.id, posts.active, posts.title, posts.close_date, users.name')
->from('posts')
->join('users', 'posts.user_id = users.id', 'left')
->where('posts.active','1')
->where(['posts.active' => '1', 'posts.close_date >=' => date('Y-m-d')])
->order_by('posts.updated_at', 'DESC')->get();
return $q;
}
How can I list all posts with count posts for each user (count only posts where posts.active = 1 and posts.close_date >= current date)?
If CI can't do the job, please give me the sql query.
Here you go:
With complex queries like this, the best way is to store the sql script in a string variable and use $this->db->query() to execute it.
This query is in MySQL:
public function get_posts() {
$sql = "
SELECT `posts`.`id`, `posts`.`active`, `posts`.`title`, `posts`.`close_date`, users.name, COUNT(`posts`.`user_id`) AS `active_post_count`
FROM `posts`
LEFT JOIN `users` ON `posts`.`user_id` = `users`.`id`
WHERE `posts`.`active` = ?
AND `posts.close_date` >= ?
ORDER BY `posts`.`updated_at` DESC;
";
$now = new DateTime('now');
$binds = [1, $now->format('Y-m-d H:i:s')];
return $this->db->query($sql, $binds)->result_array();
}
Here's a sample code on how to access the post count:
$this->Your_model->get_posts()[0]['active_post_count'];
See CodeIgniter's docs on Generating Query Results:
If you want the result as an object instead, use result_object() over result_array().

Grails Criteria distinct doesn't work

In my app I use createCriteria for getting a list according some criteria.
roleMapping contains user.
I use the following code:
def getTeamOfCompany(def company,def offset=0){
def c = roleMapping.createCriteria()
def result = c.list{
eq('company',company)
eq('isCurrentCompany',true)
firstResult offset
maxResults 10
distinct('user')
user{
order "lastname", "asc"
}
}
return result
}
I use the distinct in order to not get the same user twice, but it didn't work.
If I put projections on the distinct I'll get a list of users instead roleMapping

How can I express this SQL in Elasticsearch-rails and Elasticsearch-model?

I used gem elasticsearch-rails and elasticsearch-model and I have difficult to write this query in elasticsearch-rails.
SELECT "news".* FROM "news"
WHERE "news"."is_active" = 'true' AND
((priority is not null AND created_at > '2014-07-08 08:55:52.888587') OR
(created_at > '2014-07-08 08:55:52.888820' AND is_persisted = 't') )
ORDER BY "news"."priority" ASC, "news"."created_at" DESC
LIMIT 10 OFFSET 0
In my previous project I used "Tire Model", I used something like this:
filter :bool, must: {and: [{term: {field with options}}, {term: {field with options}}]}, It works in tire model
But if I use something like this in elasticsearch-rails, it throws missing filtered error
I write something like this for filtering active record:
def self.news_index(page = 1)
query =:
response=self.elasticsearch.search query: { match: { is_active: true }}
response=response.page(page)
end
In the above method, I want to add combined filter with bool option. Can anyone guide me?
Elasticsearch-ruby is far closer to the elasticsearch DSL when it comes to querying. Most of the time you'll be passing in hashes (or hash-like objects) to the query method.
Something like this should get you close:
self.search query: {
filtered: {
query: { match: { is_active: true }},
filter: {
bool: {
must: {
and: [{term: {field with options}}, {term: {field with options}}]
}
}
}
}
}
The difference is that instead of filter being a method call in the tire query which took arguments :bool and the filter. You now need to specify a :filter key with a hash value which then contains a :bool key with your existing filter as the value.

Resources