I need to search a list of keyword in Room. Currently i can search a single keyword like:
#Query("SELECT * FROM customer where content LIKE '%' || :keyword || '%' and status = 'published'")
LiveData<List<Customer>> getSearchResult(String keyword);
But how can i search a list of keyword in a easy way.
Is there easy way like IN with Collection arguments like:
#Query("SELECT first_name, last_name FROM user WHERE region IN (:regions)")
public List<NameTuple> loadUsersFromRegions(List<String> regions);
I know i can build query for multiple keyword manually but i want to pass a Collection as a argument.
Thanks in advance.
In SQL this is an easy thing to do by using FTS3 or FTS4 it's a Full Text Search these two are the newest features in SQL but I'm struggling on how to configure this into my android projects. I under stand a bit about room but not enough to give a an accurate answer I'm still researching this myself but have not found an answer. Please let me know if you find a way to configure it. I've been on this issue for weeks now but I know from knowing more about SQL that it is the FTS functions that are needed.
I have used below code for FTS search. Joined keyword with OR
String keywordAll = TextUtils.join("* OR *", keywordList);
keywordAll = "*" + keywordAll + "*";
For query used MATCH for search
WHERE Posts MATCH :keyword
Hope this will help others.
Related
Question
Is it possible to dynamically build the filtering for a query?
The problem
I have a big list, addresses. The user can filter it with typing text in a SearchView. If the user put any space in the text it will be divided and the two part of the text will be searched separately. I have to build the SQL dynamically because I didn't know how many space characters will be. Is there any way to handle this in Room whit simple #Query or I have to use #RawQuery for this?
Example SQL for this:
SELECT * FROM ADDRESS WHERE (CITY LIKE '%abc%' OR STREET LIKE '%abc%') AND (CITY LIKE '%abc%' OR STREET LIKE '%def%') AND (....)
I think what you should do is use RawQuery.
Since your query is complicated and you are not sure how long it is, you should probably construct it in runtime and execute it as well.
Room check the validity of the #Query in compile time so I think you'll have a hard time to implement it that way.
This example is taken from the documentation:
#Dao
interface RawDao {
#RawQuery
User getUserViaQuery(SupportSQLiteQuery query);
}
SimpleSQLiteQuery query = new SimpleSQLiteQuery("SELECT * FROM User WHERE id = ? LIMIT 1", new Object[]{userId});
User user2 = rawDao.getUserViaQuery(query);
You can pass those words in an array
#Query("SELECT * FROM ADDRESS WHERE CITY LIKE(:keywords)") //customize your query here
List addresses(String[] keywords);
I have a code where I want to search the database with matches on the user's input using multiple like query.
code:-
String querysearch= "SELECT * FROM Data WHERE Value LIKE ? AND ObjectID LIKE ?"
cursor = sqldb.rawQuery(querysearch, new String[]{"%"+query + "%", " %"+query+"%"});
Based on what I've recently searched, I came up with that but unfortunately, it did not return any matches eventhough it has. Any help? Thanks!
Solved it. The problem is with me using the AND operator. If you want to strictly match your results, with the two conditions, use AND. But if you want whichever of your conditions to provide the match on your desired result, use OR.
i`m trying to search a Sqlite Database , with this condition : i want to find a string using an Exact Keyword. let me explain this to you .
i have 3 rows as follow :
catching cold
i have a cat
two cats was seen in your house yesterday
i want to search these rows with keyword "cat" and i expect this result :
i have a cat
i am using this SQL code so far :
Select * FROM MyTable WHERE Mycolumn Like '%cat%'
But Returning Result is All these 3 Rows:
catching cold
i have a cat
two cats was seen in your house yesterday
What can i do to get my expected result?
thank you in advance.
The % character in the argument of a LIKE clause matches any string, including the empty string. Unfortunately, SQLite doesn't have the REGEXP function built in (and Android's SQLite doesn't have it).
What you can do instead is use FTS (full text search). How to do so is described here: https://www.sqlite.org/fts3.html#section_1_2
Using your example, you would set it up like so:
create virtual table textsearch using fts4(content);
insert into textsearch (content) values ('catching cold'), ('i have a cat'), ('two cats was seen in your house yesterday')
Then you can do a simple text query with the MATCH operator:
select * from textsearch where content match 'cat';
If you try the above in a sqlite3 shell, you'll see it returns only 'i have a cat'. There's a lot more you can do with the match operator, explained on the page I linked above.
You can use a regular expression with a special pattern for word boundaries.
Select * FROM MyTable WHERE Mycolumn = 'cat'
Corrected my answer i think that should work.
I have a Sqlite3 database in android, with data are sentences like: "good afternoon" or "have a nice day", now I want to have a search box, to search between them, I use something like this :
Cursor cursor = sqliteDB.rawQuery("SELECT id FROM category WHERE sentences LIKE '"+ s.toString().toLowerCase()+ "%' LIMIT 10", null);
But it only show "good afternoon" as result if user start searching with first "g" or "go" or "goo" or etc, how can I retrieve "good afternoon" as results, if user search like "a" or "af" or "afternoon".
I mean I want to show "good afternoon" result, if user search from middle of a data in sqlite3 db, not only if user searches from beginning.
thanks!
Just put the percent sign in front of your query string: LIKE '%afternoon%'. However, your approach has two flaws:
It is susceptible to SQL injection attacks because you just insert unfiltered user input into your SQL query string. Use the query parameter syntax instead by re-writing your query as follows:
SELECT id FROM category WHERE sentences LIKE ? LIMIT 10. Add the user input string as selection argument to your query method call
It will be dead slow the bigger your database grows because LIKE queries are not optimized for quick string matching and lookups.
In order to solve number 2 you should use SQLite's FTS3 extension which greatly speeds up any text-related searches. Instead of LIKE you would be using the MATCH operator that uses a different query syntax:
SELECT id FROM category WHERE sentences MATCH 'afternoon' LIMIT 10
As you can see the MATCH operator does not need percent signs. It just tries to find any occurrence of a word in the whole text that is being searched (in your case the sentences column). Read through the documentation of FTS3 I've linked to. The MATCH query syntax provides some more pretty handy and powerful options for finding text in your database table which are pretty similar to early search engine query syntax such as:
MATCH 'afternoon OR evening'
The only (minor) downside to the FTS3 extension is that it blows up the database file size by creating additional search index tables and meta-data. But I think it's well worth it for this use case.
In my application ,am work with a large database.Nearly 75000 records present in a table(totally 6 tables are there).i want to get a data from three different table at a time.i completed that.but the search process was slow.how can i optimise the searching process?
You might want to consider using the full-text search engine and issuing SELECT...MATCH queries instead. Note that you need to enable the FTS engine (it's disabled by default) and create virtual tables instead of regular tables. You can read more about it here.
Without being able to see the table structure (or query) the first thing I'd suggest is adding some indexes to the tables.
Lets say you have a few tables like:
Author
id
last_name
first_name
Subject
id
name
Book
id
title
author_id
subject_id
and you're wanting to get all the information about each of the books that an author with last_name="Smith" and first_name="John" wrote. Your query might look something like this:
SELECT * FROM Book b
LEFT JOIN Subject s
ON s.id=b.subject_id
LEFT JOIN Author a
ON a.id=b.author_id
WHERE a.last_name='Smith'
AND a.first_name='John';
There you'd want the last_name column in the Author table to have an index (and maybe first_name too).