Rails: Find all records where string column contains all words from an array of strings - rails-activerecord

How to filter all the records from a table where a column 'name' is like (in any order) all the values from an array of strings

You could use REGEXP
Model.where('name REGEXP ?', array_of_string.join('|'))

If you're using postgres DB please check the following answer since postgress has arrays.
You might want to do it at application level if your db is small.
If REGEXP is viable to you then the #khiav reoy answer is the best you could do.

Related

How to get the list after splitting the string using splitPart in jOOQ?

I have a field tags which is a string formed by comma-separated strings.
When I try to get the data from the database I want them to be separated.
jsonObject(
.......
key("tags").value(splitPart(TABLENAME.TAGS, ",", 1))
.......
)
From the above, I can only get one value but I want the entire array.
What should I do to get the entire array after splitting?
Unfortunately, the PostgreSQL SPLIT_PART function doesn't allow for accessing the entire split array, only a "part". You probably want to use string_to_array instead? That will produce a PostgreSQL array, which can be converted to a JSON(B) using the array_to_json function.
jOOQ does not yet support the latter (see #12841), but as always, when jOOQ doesn't know a vendor-specific SQL feature, you can easily resort to using plain SQL templating.

Laravel - check for string before another string

I have a Laravel where clause in which I check if a column contains a certain string
->where('column_name', 'like', '%{string}%'). I want to update it so I can look for this string before a certain word is in the column. So if I have in the column: "This is dog but this is new dog." I have 2 occurrences of dog and I want the first one before the word new.
This is normally done using regex
If it is possible to get the query result and do a regex, that would be better
I can give you two links that can help you Laravel raw queries and MySQL regexp
If I get you correctly, you are looking for two words that appear in the column and precede each other. If that's the case, you can concatenate the two strings like so
->where('column_name', 'like', '%{firstString} {string}%')

Best way to compare field against array of strings with Sequel Gem?

If I need to check a field in a table against an array of possible strings (using Postgres with the Sequel gem), what's the fastest way to do so? I've tried building a regular expression from the array with |'s inbetween each entry, and then using it to search the table using .where, but it's slow... and I'm hoping there may be a faster way.
If your field can be equal to one of multiple words, you can use :
SELECT * FROM table WHERE field IN ('apple', 'banana', 'carrot', 'dog', ....)
PostgreSQL will probably not use an index for a regular expression lookup with |s, which would explain the slow speed on large datasets. The IN operator is what you want to use, as it should be able to use an index lookup (assuming the appropriate index). In Sequel:
DB[:table].where(:field=>['string1', 'string2', 'string3'])

Sorting jsonb objects in Postgresql 9.4

The problem that I am facing is not that I'm not able to perform a sort, but rather a correct sort. That is, my objects that are stored as jsonb need to be sorted before getting displayed in a table. Part of the query that sorts is:
ORDER BY data ->> 'Name' ASC
However the problem is that at its current state, psql returns the list of people ordered by two clusters: upper and lower case. ASC sort returns sorted upcase + sorted downcase while DESC returns inverted sort downcase + inverted sort upcase.
Is there a trick behind sorting the data in a caseless order or does the data need to initially be stored in a particular case.
ORDER BY lower(data ->> 'Name') ASC
This does create a temporary fix, but I will be glad if there are other methods out there
Sorting by jsonb value works the same as sorting by simple text field. If you get case-sensitive sorting, you likely set incorrect collation to your database.
See this issue, answer by MichaƂ Niklas.

SQLite - how to return rows containing a text field that contains one or more strings?

I need to query a table in an SQLite database to return all the rows in a table that match a given set of words.
To be more precise: I have a database with ~80,000 records in it. One of the fields is a text field with around 100-200 words per record. What I want to be able to do is take a list of 200 single word keywords {"apple", "orange", "pear", ... } and retrieve a set of all the records in the table that contain at least one of the keyword terms in the description column.
The immediately obvious way to do this is with something like this:
SELECT stuff FROM table
WHERE (description LIKE '% apple %') or (description LIKE '% orange %') or ...
If I have 200 terms, I end up with a big and nasty looking SQL statement that seems to me to be clumsy, smacks of bad practice, and not surprisingly takes a long time to process - more than a second per 1000 records.
This answer Better performance for SQLite Select Statement seemed close to what I need, and as a result I created an index, but according to http://www.sqlite.org/optoverview.html sqlite doesn't use any optimisations if the LIKE operator is used with a beginning % wildcard.
Not being an SQL expert, I am assuming I'm doing this the dumb way. I was wondering if someone with more experience could suggest a more sensible and perhaps more efficient way of doing this?
Alternatively, is there a better approach I could use to the problem?
Using the SQLite fulltext search would be faster than a LIKE '%...%' query. I don't think there's any database that can use an index for a query beginning with %, as if the database doesn't know what the query starts with then it can't use the index to look it up.
An alternative approach is putting the keywords in a separate table instead, and making an intermediate table that has the information about which row in your main table has which keywords. If you indexed all the relevant columns that way, it could be queried very quickly.
Sounds like you might want to have a look at Full Text Search. It was contributed to SQLite by someone from google. The description:
allows the user to efficiently query
the database for all rows that contain
one or more words (hereafter
"tokens"), even if the table contains
many large documents.
This is the same problem as full-text search, right? In which case, you need some help from the DB to construct indexes into these fields if you want to do this efficiently. A quick search for SQLite full text search yields this page.
The solution you correctly identify as clumsy is probably going to do up to 200 regular expression matches per document in the worst case (i.e. when a document doesn't match), where each match has to traverse the entire field. Using the index approach will mean that your search speed will be independent of the size of each document.

Resources