Ruby On Rails searching database for word - ruby-on-rails

I am new to rails. I am trying to search a database in MySQL where the term I am searching may be one word in the column string. For example if the cell was "this is a very lovely day" then I would like to be able to call that object by searching for the word 'lovely'
Thank you.

You need to do a LIKE query. (i.e. foo LIKE %bar%) The % represents a wildcard operator. bar% would be "starts with bar" and %bar% would be "contains bar." Note that contains searches cannot use column indexes and will be slow.
Suppose you had a Day class with the attribute description. In that case, you would do
Day.where("description LIKE '%lovely%')

by using Arel
days = Day.arel_table
Day.where(days[:description].matches("%lovely%"))

Related

How to store regex or search terms in Postgres database and evaluate in Rails Query?

I am having trouble with a DB query in a Rails app. I want to store various search terms (say 100 of them) and then evaluate against a value dynamically. All the examples of SIMILAR TO or ~ (regex) in Postgres I can find use a fixed string within the query, while I want to look the query up from a row.
Example:
Table: Post
column term varchar(256)
(plus regular id, Rails stuff etc)
input = "Foo bar"
Post.where("term ~* ?", input)
So term is VARCHAR column name containing the data of at least one row with the value:
^foo*$
Unless I put an exact match (e.g. "Foo bar" in term) this never returns a result.
I would also like to ideally use expressions like
(^foo.*$|^second.*$)
i.e. multiple search terms as well, so it would match with 'Foo Bar' or 'Search Example'.
I think this is to do with Ruby or ActiveRecord stripping down something? Or I'm on the wrong track and can't use regex or SIMILAR TO with row data values like this?
Alternative suggestions on how to do this also appreciated.
The Postgres regular expression match operators have the regex on the right and the string on the left. See the examples: https://www.postgresql.org/docs/9.3/static/functions-matching.html#FUNCTIONS-POSIX-TABLE
But in your query you're treating term as the string and the 'Foo bar' as the regex (you've swapped them). That's why the only term that matches is the exact match. Try:
Post.where("? ~* term", input)

Rails NOT IN query and regexp

I have array of strings:
a = ['*#foo.com', '*#bar.com', '*#baz.com']
I would like to query my model so I will get all the records where email isn't in any of above domains.
I could do:
Model.where.not(email: a)
If the list would be a list of strings but the list is more of a regexp.
It depends on your database adapter. You will probably be able to use raw SQL to write this type of query. For example in postgres you could do:
Model.where("email NOT SIMILAR TO '%#foo.com'")
I'm not saying thats exactly how you should be doing it but it's worth looking up your database's query language and see if anything matches your needs.
In your example you would have to join together your matchers as a single string and interpolate it into the query.
a = ['%#foo.com', '%#bar.com', '%#baz.com']
Model.where("email NOT SIMILAR TO ?", a.join("|"))
Use this code:
a = ['%#foo.com', '%#bar.com', '%#baz.com']
Model.where.not("email like ?",a.join("|"))
Replace * to % in array.

Postgresql text searching, matching multiple words

I don't know the name for this kind of search, but I see that it's getting pretty common.
Let's say I have records with the following file names:
'order_spec.rb', 'order.sass', 'orders_controller_spec.rb'
If I search with the following string 'oc' I would like the result to return 'orders_controller_spec.rb' due to match the o in orders and the c in controller.
If the string is 'os' then I'd like all 3 to match, 'order_spec.rb', 'order.sass', 'orders_controller_spec.rb'.
If the string is 'oco' then I'd like 'orders_controller_spec.rb'
What is the name for this kind of search and how would I go about getting this done in Postgresql?
This is a called a subsequence search. One simple way to do it in Postgres is to use the LIKE operator (or several of the other options in those docs) and fill the spaces between your letters with a wildcard, which for LIKE is %. To match anything with an o followed by an s in the words column, that would look like this:
SELECT * FROM table WHERE words LIKE '%o%s%';
This is a relatively expensive search, but you can improve performance with a varchar_pattern_ops or text_pattern_ops index to support faster pattern matching.
CREATE INDEX pattern_index ON table (words varchar_pattern_ops);

How to sort a list of 1million records by the first letter of the title

I have a table with 1 million+ records that contain names. I would like to be able to sort the list by the first letter in the name.
.. ABCDEFGHIJKLMNOPQRSTUVWXYZ
What is the most efficient way to setup the db table to allow for searching by the first character in the table.name field?
The best idea right now is to add an extra field which stores the first character of the name as an observer, index that field and then sort by that field. Problem is it's no longer necessarily alphabetical.
Any suggestions?
You said in a comment:
so lets ignore the first letter part. How can I all records that start with A? All A's no B...z ? Thanks – AnApprentice Feb 21 at 15:30
I issume you meant How can I RETURN all records...
This is the answer:
select * from t
where substr(name, 1, 1) = 'A'
I agree with the questions above as to why you would want to do this -- a regular index on the whole field is functionally equivalent. PostgreSQL (with some new ones in v. 9) has some rather powerful indexing capabilities for special cases which you might want to read about here http://www.postgresql.org/docs/9.1/interactive/sql-createindex.html

Symfony, propel, question mark

I want to create a search function on my website, and I don't want to use a plugin for this thing, because it's very simple, but I can't solve this problem:
I give the keyword to the model which creates a query, but I couldn't figure out how to put joker characters in this query.
I'm using Propel
Dennis
The filterByXXX() query functions will use LIKE when your query contains wildcards:
$books = BookQuery::create()
->filterByTitle('War%')
->find();
// example Query generated for a MySQL database
$query = 'SELECT book.* from `book` WHERE book.TITLE LIKE :p1'; // :p1 => 'War%'
Remember, the wildcards you can use in SQL are _ for exactly one and % for zero or more characters. So not ? or *.

Resources