Optimizing SQLite multiple LIKE search for iOS - ios

I'm executing an SQLite select statement with several LIKE clauses in an iPhone application. The statements resemble the following:
SELECT * FROM mytable
WHERE name LIKE 'Smith %'
OR name LIKE '% Smith %'
OR name LIKE 'Smith_%'
OR name LIKE '% Smith_%';
The execution currently takes about 0.5 seconds on my laptop and about 2 seconds on the device. I can't index the "name" column of "mytable" because of space constraints.
Each of the LIKE clauses is quite similar - if one fails, it's likely they each will. So I'd like to group these together some how to optimize my search.
Can this be done, say via REGEXP? If so, how and is REGEXP enabled by default?
Edit. I'm trying statements along the lines of:
SELECT * FROM mytable WHERE name REGEXP '[ _]?Smith[ _,]';

SQLite actually has a full text search engine built in. You may want to consider using it.
http://www.sqlite.org/fts3.html#section_1

Related

Blazer - Escape Characters

I feel like I am missing something, but I could not find it in the documentation on GH.
What are the escape characters for Blazer when searching in a string that contains a ' or ".
Example:
SELECT * FROM "search_filters"
where "params" like '%with_vehicles_id"=>[%'
LIMIT 100
Update:
The underlying database is Postgres 11. This is a blazer tool question, as the query above works just fine in a tool like dBeaver, or console. For some reason, I believe this is related to how Blazer is parsing the query before it is sent.
I'm not very familiar with Blazer but it looks like it's a BI tool that lets your run SQL queries against your database and there's a playground here.
For PostgreSQL you don't need to do anything special for a double-quote inside of single quotes. The query as you wrote it would execute in a postgres terminal and the same approach works in the blazer playground.
SELECT * FROM "search_filters"
where "params" like '%text"text%'
LIMIT 100
To query on a string that includes a single quote, PosgreSQL has you use two sequential single quotes, like this:
SELECT * FROM "search_filters"
where "params" like '%text''text%'
LIMIT 100
Here's a link with more information:
https://www.prisma.io/dataguide/postgresql/short-guides/quoting-rules
-- UPDATE --
Based on your error message ("syntax error at or near "LIMIT" LINE 3: LIMIT 100 LIMIT 1000") it looks like there are two "LIMIT" clauses being added to the SQL query. Do you have gems/plugins that are modifying the query and is there a way to disable them to see if that's causing the problem?

search column for name is similar in rails

So i have two tables, Table 1 and Table 2
In Table 1 there is a column called event name
In Table 2 there is a column called description
Now the issue I'm having is I am needing to link rows together, the issue is one of the event names shows as this:
xyz presents: The Alphabet and Friends
And the description shows as
Alphabet and Friends
So the issue im having is i'm trying it like this:
Table2.where("description LIKE ?", "%xyz presents: The Alphabet and Friends%")
And the above is not finding anything as i expected, If i removed the first 3 words, it matches but i cannot trust this as a solution.
Any recommendations on how to fix this?
Searching with LIKE works as expected. It seems that you expect it to somehow know which words to ignore it it's match which it doesn't. Why can't you just do?
Table2.where("description LIKE ?", "%The Alphabet and Friends%")
If you need to search a few terms you could do:
Table2.where("description LIKE ? or description LIKE ?",
"%The Alphabet and Friends%", "%xyz presents:%")

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);

SQLite slow query on iPad

I have a table with almost 300K records in it. I run a simple select statement with a where clause on an indexed column ('type' is indexed):
SELECT *
FROM Asset_Spec
WHERE type = 'County'
That query is fast - about 1 second. Additionally I want to test against status:
SELECT *
FROM Asset_Spec
WHERE type = 'County'
AND status = 'Active'
The second one is VERY slow (minutes). Status is NOT indexed and in this particular case 99.9% of values in the db ARE 'Active'.
Any ideas how I can get better performance? We are compiling our own version of SQLite so I can tweak many settings (FYI - same performance on iOS pre-canned SQLite)
I looked at the query plan and the estimate for number of rows was off by an astounding amount. Asset_Spec (~2 rows) - actual number of rows is almost 300,000. Ran 'ANALYZE' - now the same query runs in 16ms.
the first thing I would try is using a subquery
SELECT * FROM
(SELECT *
FROM Asset_Spec
WHERE type = 'County')
WHERE status = 'Active'
and as Robert suggests, adding an index on any column you want to filter by is a good idea. I'd also consider changing fields Type and Status to be something other than string.
Any reason you need to select *?
Suggestions:
Do you need to retrieve multiple records? If all you need is the first record found, then add "limit 1" to the end of the query.
If you're just checking for the existence of a row, i.e. you only need to know that there is one row with status active, then "select 1" instead of "select *".

Customizing jQuery UI Autcomplete

I want to make a few customizations to jQuery UI Autcomplete:
1) If there are no results found it should output "no results found" in the list.
2) Is it possible to highlight/bold the letters in the results as they are being typed? For example if I type "ball" and I have "football" in my results it needs to output as foot ball
3) Is it possible for the results that appear at the top to match the beginning of the string. For example suppose I have 3 entries in my database:
Astrologer
Space Station
Star
I start typing "st" - this will bring up those 3 entries in that order. But I want "Star" to be the first result.
The MySQL query being used at the moment to generate the results is:
$query = mysql_query("SELECT id, name FROM customer WHERE name LIKE '%".$_GET['term']."%' ORDER BY name");
You can simply echo 'No results found' inside the script that returns the list if num rows from your mysql_query is 0.
This was possible in the original Autocomplete plugin but I can't see it anywhere in the JQuery UI documentation.
You may have to run two separate mysql queries - the first one looking for LIKE '".$_GET['term']."%' and the second one as you have it, but excluding the results you've already got from the first query.

Resources