How to query in sqlite fts3 table using "-*"? - android

I have a fts3 table named tab and a lot of entries in it. When I run this query:
SELECT * FROM tab WHERE key MATCH 'an*';
I get the results like this:
an
anul
an-
But when I run this query:
SELECT * FROM tab WHERE key MATCH 'an-*';
it still results the "an" entry. The result would be like:
an
an-
How can I write my query so the result woudn't be "an", but only those entries that actually contains the character "-"?

According to the default tokenizer rules, - separates words, and is otherwise ignored.
You have to search for the word an first, and check for the hyphen afterwards:
SELECT *
FROM tab
WHERE key MATCH 'an'
AND key LIKE 'an-%';

Related

Android SQLite additional WHERE condition after MATCH

In Android SQLite i got tabel like this
domainObjectId: String // like '9876543210'
name: String
description: String
I want to use FTS on this to search without worrying about diacritical marks, how ever i want to let user select also by typing part of object ID(ex. last 4 char)
I got select like
`SELECT * FROM tabel LEFT JOIN tabel_fts on tabel_fts.domainObjectId = tabel.domainObjectId WHERE tabel_fts MATCH '3210*' OR tabel.domainObjectId LIKE '%3210%'
But in return i get error
unable to use function MATCH in the requested context (code 1 SQLITE_ERROR);
Is this possible to add additional condition to select with MATCH?
Try to remove "MATCH" into separate "SELECT":
`SELECT * FROM tabel LEFT JOIN (select * from tabel_fts WHERE tabel_fts.domainObjectId MATCH '3210*') as tabel_fts WHERE tabel.domainObjectId LIKE '%3210%' OR table_fts.ID IS NOT NULL
By the way:
In your "WHERE tabel_fts" it seemed you've missed a column name
There is no "ON" condition in tables JOINm just "WHERE". That's OK? May be it would be better to use UNION?

Combine MATCH with OR clause in the WHERE statement

I want to perform a query in which the WHERE clausule has the following condition:
one MATCH condition over a column in a FTS3 table
OR
another not MATCH condition over a column in a non FTS table.
Example:
Say that I have two tables
books_fts, which is a table with a content column for full text search.
books_tags, which is non FTS table with tags.
I want to search all the books that either contain 'Dikjstra' in their content or are tagged with the 'algorithm' word. So I run this query:
SELECT * from books_fts
LEFT OUTER JOIN books_tags ON books_fts.fk_id = books_tags.id
WHERE (books_fts MATCH 'content:%Dijkstra*')
OR (books_tags.tag = 'algorithm')
I think the query is right, and if I run it with either one of the OR clausules, it works.
However, when running it with the two clausules I get the following error:
unable to use function MATCH in the requested context
Seems to me that I cannot combine a MATCH with a non MATCH in the WHERE clause, even if each of them apply to different tables (one FTS and another non FTS).
Is this true? I cannot find information on it.
NOTE: if the causules are separated with AND instead of OR the query is valid.
Thanks.
It seems it's a known issue in SQL:
http://sqlite.1065341.n5.nabble.com/FTS3-bug-with-MATCH-plus-OR-td50714.html

How to do a word search on a large text database

I have a large database in my app. One column is made of text strings that are about a sentence to a paragraph long. I would like to make this column searchable by word(s) that the user inputs.
How would I make a quick search? I've heard of making an index but I don't know how to do that for a text search.
SQLite has a mechanism for storing a lot of text in a database, it's called FTS (short for full text search).
Android supports all SQLite commands, so you can easily just use FTS3.
How is explained in the documentation linked above.
Example for creating a table:
CREATE VIRTUAL TABLE enrondata1 USING fts3(content TEXT); /* FTS3 table */
CREATE TABLE enrondata2(content TEXT); /* Ordinary table */
Query:
SELECT count(*) FROM enrondata1 WHERE content MATCH 'linux'; /* 0.03 seconds */
SELECT count(*) FROM enrondata2 WHERE content LIKE '%linux%'; /* 22.5 seconds */

SQLite Fts select query

I am making a dictionary of over 20,000 words in it. So, to make it work faster when search data, i am using fts3 table to do it.
my select query:
Cursor c=db.rawQuery("Select * from data where Word MATCH '"+word+"*'", null);
Using this query, it will show all the word that contain 'word' , but what i want is to get only the word that contain the beginning of the searching word.
Mean that i want it work like this query:
Cursor c=db.rawQuery("Select * from data where Word like '"+word+"%'", null);
Ex: I have : apple, app, and, book, bad, cat, car.
when I type 'a': i want it to show only: apple, app, and
What can i solve with this?
table(_id primary key not null autoincrement, word text)
FTS table does not use the above attributes. It ignores data type. It does not auto increment columns other than the hidden rowid column. "_id" will not act as a primary key here. Please verify that you are implementing an FTS table
https://www.sqlite.org/fts3.html
a datatype name may be optionally specified for each column. This is
pure syntactic sugar, the supplied typenames are not used by FTS or
the SQLite core for any purpose. The same applies to any constraints
specified along with an FTS column name - they are parsed but not used
or recorded by the system in any way.
As for your original question, match "abc*" already searches from the beginning of the word. For instance match "man*" will not match "woman".
FTS supports searching for the beginning of a string with ^:
SELECT * FROM FtsTable WHERE Word MATCH '^word*'
However, the full-text search index is designed to find words inside larger texts.
If your Word column contains only a single word, your query is more efficient if you use LIKE 'a%' and rely on a normal index.
To allow an index to be used with LIKE, the table column must have TEXT affinity, and the index must be declared as COLLATE NOCASE (because LIKE is not case sensitive):
CREATE TABLE data (
...
Word TEXT,
...
);
CREATE INDEX data_Word_index ON data(Word COLLATE NOCASE);
If you were to use GLOB instead, the index would have to be case sensitive (the default).
You can use EXPLAIN QUERY PLAN to check whether the query uses the index:
sqlite> EXPLAIN QUERY PLAN SELECT * FROM data WHERE Word LIKE 'a%';
0|0|0|SEARCH TABLE data USING INDEX data_Word_index (Word>? AND Word<?)

How to query similar records in SQLite database from Android?

Let's say an SQLite database column contains the following value:
U Walther-Schreiber-Platz
Using a query I'd like to find this record, or any similar records, if the user searches for the following strings:
walther schreiber
u walther
walther-schreiber platz
[Any other similar strings]
However I cannot figure out any query which would do that. Especially if the user does not enter the - character.
Example:
select * from myTable where value like '%walther schreiber%'; would not return the result because of the missing -.
Thanks,
Robert
So, as I said in my comment, I think you can have a query along the lines of:
select * from myTable where LOWER(value) like <SearchValue>
I'm assuming you're collecting the <SearchValue> from the user programmatically, so would be able to do the following: <SearchValue> would need to be: The user's search string, appropriately cleansed to avoid SQL injection attacks, converted to lower case, with all of the spaces converted to '%', so that they match zero or more characters...
So you would have (for example):
select * from myTable where LOWER(value) like '%walther%schreiber%'
select * from myTable where LOWER(value) like '%walther-schreiber%platz%'
etc... however, this does assume that the word order is the same, which in your examples it is...

Categories

Resources