ruby sequel gem - how to query arrays with the pg_array extension - ruby

I am using the pg_array extension and sequel version 4.1.1.
I have added the extension like this:
Sequel::Database.extension :pg_array
I have created a column like this:
alter_table :emails do
add_column :references, "text[]", null: true
end
I can load and retrieve arrays into a postgress array column, just like working with normal arrays.
What is not clear from the above link is how do I execute a query based on the values in this array column.
For example, if one row in the emails table contained these values in the references column:
references
--------------------------------------------------------------------
{}
{5363f773bccf9_32123fe75c45e6f090953#Pauls-MacBook-Pro.local.mail}
How can I query the emails table to find a row that contains a references array value of the above value:
Email.where(references: ????)

Use the pg_array_ops extension:
Sequel.extension :pg_array_ops
Email.where(Sequel.pg_array_op(:references).contains('5363f773bccf9_32123fe75c45e6f090953#Pauls-MacBook-Pro.local.mail'))

Have you tried?
ref = '5363f773bccf9'
emails = Email.arel_table
Email.where( emails[ :references ].matches( "%#{ref}%" ))

Related

Reference database column with variable in sequel sinatra

How do I refernce the column in the database with the column variable in the url/route. The column varible is a string coming from a webpage, and I have to reference the column with a hash key.
Sinatra route:
get '/users/update/:id/:column/:value' do
User.where(id: params[:id]).update(column: params[:value])
redirect back
end
Html:
Value
If you are looking to use params[:column] as a variable key in the update you can use the hash rocket syntax:
User.where(id: params[:id]).update(params[:column] => params[:value])

How to put the "text" into a database?

I generated the following using a Keyword extraction API
(I searched for "Hitler" because no one is trying to sell you things when you search for him.)
x=[{"relevance"=>"0.592174", "text"=>"eight-year-old Hitler"}, {"relevance"=>"0.589796", "text"=>"Hitler states"}, {"relevance"=>"0.589118", "text"=>"Hitler lived."}, {"relevance"=>"0.585102", "text"=>"Hitler learnt"}, {"relevance"=>"0.580278", "text"=>"Hitler Youth"}, {"relevance"=>"0.414842", "text"=>"German Workers"}, {"relevance"=>"0.413532", "text"=>"German military leaders"}, {"relevance"=>"0.404701", "text"=>"nazi party"}, {"relevance"=>"0.391943", "text"=>"Mein Kampf"}, {"relevance"=>"0.388932", "text"=>"Reichstag"}, ]
So the database should have :
Eight-year-old hitler
Hitler states
...
I've tried x.each do |x| and
x.to_a.each do
x["text"]
x
None of which work.
Since you haven't given the following information, I will make some assumptions:
Database table name
Schema for table
Model name
ORM
Let's rename x to search_results. Let's also assume that we have a table in the database called search_results, a model called SearchResult, that the search_results table has a column called text, and that we are using ActiveRecord as the ORM:
search_results.each do |data|
SearchResult.create(text: data[:text])
end
Or since you have an array of hashes, simply:
SearchResult.create(search_results)

Sequel Migration update with a row's ID

How can you run a Sequel migration that updates a newly added column with a value from the row?
The Sequel documentation shows how you can update the column with a static value:
self[:artists].update(:location=>'Sacramento')
What I need to do is update the new column with the value of the ID column:
something like:
self[:artists].each |artist| do
artist.update(:location => artist[:id])
end
But the above doesn't work and I have been unable to figure out how to get it to go.
Thanks!
artist in your loop is a Hash, so you are calling Hash#update, which just updates the Hash instance, it doesn't modify the database. That's why your loop doesn't appear to do anything.
I could explain how to make the loop work (using all instead of each and updating a dataset restricted to the matching primary key value), but since you are just assigning the value of one column to the value of another column for all rows, you can just do:
self[:artists].update(:location=>:id)
if you need update all rows of a table, because it is a new column that need be populate
artists = DB[:artists]
artists.update(:column_name => 'new value')
or if you need, update only a unique row into your migration file you can:
artists = DB[:artists]
artists.where(:id => 1).update(:column_name1 => 'new value1', :column_name2 => "other")

Compare string ID to BSON::ObjectId

I have an array of made up of type BSON::ObjectId and I want it to compare against some IDs as strings.
if my_array_of_BSON_ObjectIds.include?(#my_id_as_a_string)
# delete the item from the array
else
# add the item to the array as a BSON::ObjectId
end
This is not working as the types are different, can I turn my string into a BSON::ObjectId? If so, how?
Mongoid 2.x with 10gen's driver:
BSON::ObjectId.new('506144650ed4c08d84000001')
Mongoid 3 with moped:
Moped::BSON::ObjectId.from_string('506144650ed4c08d84000001')
Mongoid 4 (moped) / Mongoid 5/6/7 (mongo):
BSON::ObjectId.from_string('506144650ed4c08d84000001')
You can use BSON::ObjectId(#my_id_as_a_string) for representation your id as BSON::ObjectId
refs http://api.mongodb.org/ruby/current/BSON.html#ObjectId-class_method
collection.delete_one({"_id"=>BSON::ObjectId(params['id'])})
This worked for me and it deleted the record from the database successfully
There's a shorter way:
BSON::ObjectId("id_here")
but for your case it would be easier to simply map the objects to ids before the comparison:
if my_array_of_BSON_ObjectIds..map(&:to_s).include?(#my_id_as_a_string)

Timestamp Column from Joined Table Becomes String

I have a table named subs which has many articles. The articles table has a timestamp column called published.
Sub.select( "subs.*,MAX(articles.published) published").joins("LEFT OUTER JOIN articles ON subs.id=articles.sub_id").group("subs.id").first.published.class
=> String
Article.select("max(published) published").group("id").first.published.class
=> ActiveSupport::TimeWithZone
I want to get an ActiveSupport::TimeWithZone object back from the first query.
Rails 3
Rails determines how to type cast attributes based on their database column definitions. For example, say you have a created_at method on your Sub model. When a record is loaded read_attribute is used (ActiveRecord::AttributeMethods::Read). This uses type_cast_attribute which determines how to cast the value based on the column info. For example, if you are using PostgreSQL it may use:
Sub.columns.detect { |c| c.name == "created_at" }.type_cast_code("v")
=> "ActiveRecord::ConnectionAdapters::PostgreSQLColumn.string_to_time(v)"
But Rails doesn't know what to do with columns that aren't on the Sub model. So it just gives back a String. If you need to work with a ActiveSupport::TimeWithZone object, you can cast the value with:
published = Sub.select( "subs.*,MAX(articles.published) published").joins("LEFT OUTER JOIN articles ON subs.id=articles.sub_id").group("subs.id").first.published
published.present? ? Time.zone.parse(published) : nil
Rails 4
In Rails 4, Rails is smarter about this kind of type-casting. When the SQL is executed, ActiveRecord::Result is created and the column_types are passed to the initializer. In your example Sub.select query, the published column would be cast as a Time object.

Resources