How to fetch distinct values with arel/relational algebra - distinct

I'm doing my best to bend my brain around arel and the relational algebra behind it, but how to represent a SELECT DISTINCT is consistently eluding my comprehension. Can anyone explain how to arel:
SELECT DISTINCT title FROM posts;
Many thanks!

Using pure Arel (not Rails/ActiveRecord) there is a "distinct" method:
Arel::VERSION # => '3.0.2'
posts = Arel::Table.new(:posts)
posts.project(posts[:title])
posts.distinct
posts.to_sql # => 'SELECT DISTINCT "posts"."title" FROM "posts"'
Curiously, the "distinct" method is not chainable, per the other Arel methods.

The Arel way to do it is:
t = Arel::Table.new(:foo)
count_distinct = t[:field].count(true)
count_distinct.to_sql # => "COUNT(DISTINCT `foo`.`field`)"

The previous answer is the Rails way, no? Not the Arel way.
This works for arel 1.x:
posts = Table(:posts)
posts.project(Arel::Distinct.new(posts[:title]))
I'd guess there's another "more correct" way to do this via the API but I haven't figured that out yet.

If you are doing this using a scope:
scope :recent, lambda {|count|
select("DISTINCT posts.*").
joins(:whatever).
limit(count).
order("posts.updated_at DESC")
}

Post.select('DISTINCT title')
Update 1:
At the time of the post, this was not available in Arel. These days, ActiveRecord::QueryMethods has the uniq method (http://apidock.com/rails/ActiveRecord/QueryMethods/uniq), so you'd want:
Post.select(:title).uniq
Update 2:
Looks like Arel now supports this behavior. #maerics has the correct answer. I'd delete this if it wasn't the accepted answer.

Since AREL always uses SET in it's operation, duplicate row results will be deleted automatically. Just use a normal Project (Phi) operation.

Related

Ember Sort my Records so the null for a column are retuned first

I want to filter and then sort my ember records such that the null records for a column are returned first. I'm not much familiar with ember and have a rails back ground.
filteredByData = myLeads.filterBy('status', 'open').filterBy('doNotCall', false).filterBy('phoneValid', true)
filtered = filteredByData.sortBy 'last_dialed_at', 'last_name', 'first_name', 'id'
Right now, my records are getting ordered according to the id.
What i want is to implement the NULLS LAST/FIRST from sql or postgres in any query (such a s SELECT * FROM t1 ORDER BY c1 DESC NULLS FIRST here in my sort so i get the records such that the last_dialed_atnull records come first.
I know the same can be implemented in rails like
Foo.order('last_dialed_at DESC NULLS FIRST') but i have no idea for same in Ember
Any help will be appreciated. Thanks in Advance.
P.S: I'll try to create a ember twiddle meanwhile to explain myself better.
Although you can resort to a SortableMixin/ArrayProxy, those are lower-level APIs than you should really need to use. sortBy works fine for a single value, but I generally use computed.sort when I need to sort multiple things. Take a look at the code and link in this answer https://stackoverflow.com/a/46788377/334913 they should get you going.
One of the common ways Ember suggests doing things is to do computed properties for each step (or set of steps) as it makes it far easier to reason about.
So I would do something along the lines of:
filteredLeads: Ember.computed('leads', function() {
return filteredResultsHere;
}),
sortDefinition: [], // put your entries from your SortableMixin here
sortedFilteredLeads: Ember.computed.sort('filteredLeads', 'sortDefinition'),
I solved my issue by using the Ember.SortableMixin instead of sortBy. I ended up with the following code and this worked perfectly for me.
leads = Ember.ArrayProxy.createWithMixins Ember.SortableMixin, content: filteredByData, sortProperties: ['lastDialedAt', 'firstName', 'lastName', 'id'], sortAscending: true
I'm not sure or much aware why this worked and the fundamentals to an extent that i can explain this behaviour. If there's any explanation for same from anyone, please feel free to put your answer below and i'll accept it as the answer.
Thanks

With activerecord, how do I do a .find using an array of ids when I know that some may be missing?

I have an array of ids. Some may be in my table, some may not. I want to return the ones in the table and then create rows for missing ones. If I do a Model.find(array) I get an ActiveRecord::RecordNotFound exception if any of them are missing. The workaround I'm using is to do a .exists? for each id, but this makes for many db calls, slowing things down.
Is it possible to do a Model.find(array) without having to test each one with .exists?
Looks like find_by_id has been deprecated, but it got me looking in the right direction. Model.where(id: array) seems to do the trick.
If you use find_by_id ActiveRecord will not throw an error and SQL will only collect the existing ids.
Model.find_by_id(array)

Ruby DataMapper: How can I do pagination?

I am going to retrieve a list of objects.
get "/todoitems/?" do
debugger
todo = Todolist.all
todo.to_json
end
Is there example that can retrieve page by page?
Many thanks.
Here's a gem dm-pagination which provides pagination support for Datamapper
I also found dm-paginator
This should point you in the right direction:
http://ruby.railstutorial.org/chapters/updating-showing-and-deleting-users#sec-pagination
Essentially, there's a gem called will-paginate that takes care of sorting things in a page by page structure. There's an example included in the link

How to massive delete in php-activerecord where id NOT in list?

I'm running a CodeIgniter application with PHP-Activerecord installed and I need to do a massive delete. The PHP-AR library supports massive update and delete, but the function only takes the ids that you want to delete/update. I'm trying to do a massive delete where the ids are NOT in the list.
delete from table where id not in (1,2,3...,500)
Unfortunately, the PHP-Activerecord website is of no help, and their forums are so horribly built (no search... seriously?) that I'm truly stuck.
edit: Please note, CodeIgniter's built-in ORM is not the same as PHP-Activerecord. Just thought I'd clarify that.
A bit late but this may help someone else. In PHPActiveRecord, do it in this way:
$ids_to_delete = array(1,2,3);
YourModel::delete_all(array('conditions' => array('id NOT IN (?)', $ids_to_delete)));
Ref: http://www.phpactiverecord.org/docs/ActiveRecord/Model#methoddelete_all
SInce active record is actually build string query with function, you can use this method:
- make your list as string
- make this query : $this->db->where('id not in',$string)->delete('table')

How do I get documents more recent than a particular document in Mongoid?

I am trying to do something like this in mongoid:
User.any_in(:uid => friends).and(:id.gt => "4d391ab448fa7d389b000000").entries
But looks like Mongoid ID cannot be compared this way. How do I achieve the above without resorting to using Mongoid::Timestamps ?
Thanks!
Why would you not want to use timestamps?
Using ids in this way will not give you the behavior you want.
The id of the document will depend not only on the order of insertion but also on what machine the id was generated on.
Timestamps are definitely your best bet here.
I guess you can use server side javascript to process the values but that would be less efficient and less secure if you care for these properties.

Resources