I already read from here
FTS4 sqlite MATCH not working
and here
Full text search example in Android
but It can't solve my problem.
I have a external database and I use sqlite 3 version 3.13.0 with 2 table like this.
And I create a virtual table:
CREATE VIRTUAL TABLE tb_bank_fts USING fts4 (content="tb_bank",address, typename)
Virtual table create successfull and I can use select.
But I can't use "match" query with fts4 table, alway return null with no error.
Half month ago I can query fts4 table with "match" but now i can't do that.I don't know why. I try using SQlite Manager addon in Firefox but same problem.
The documentation says:
The FTS4 module never writes to the content table, and writing to the content table does not affect the full-text index. It is the responsibility of the user to ensure that the content table and the full-text index are consistent.
So when you've inserted data into the base table, you also have to insert it into the FTS table:
INSERT INTO tb_bank_fts(docid, address, typename)
SELECT rowid, address, typename FROM tb_bank;
or simply:
INSERT INTO tb_bank_fts(tb_bank_fts) VALUES('rebuild');
Related
I'm developing an Android app that uses a SQLite database with FTS4 tables.
In the app there's an option to import a database from the external memory. This database needs to be checked to confirm that it has all the correct tables and columns. I already have the code to do that however I don't know how to check if the tables are "normal" or FTS4. This will result in problems later on with queries with MATCH on them.
The only way I can think of to check if the tables are FTS4 is to do a random query with MATCH and if it gets an error it's because they are not.
Is there a better way to do this like with just a command?
Using MATCH on a plain table results in an error message only if the table has at least one row.
FTS table have a virtual column with the same name as the table name. So you could try a query like SELECT MyTable FROM MyTable.
You could check whether the shadow tables (MyTable_content, MyTable_segdir, etc.) exist.
You could check the CREATE TABLE statement in the system table: SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'MyTable';
Fts3 in sqlite use virtual table, that mean it use memory(ram) to store data? I have a table and only want to index one column, but fts3 require index all table, do that make increase the store data? How to index one column?
In this case, "virtual" just means that such a table is not a 'normal' SQLite table but has a custom implementation.
The documentation says:
For each FTS virtual table in a database, three to five real (non-virtual) tables are created to store the underlying data. These real tables are called "shadow tables". The real tables are named "%_content", "%_segdir", "%_segments", "%_stat", and "%_docsize", where "%" is replaced by the name of the FTS virtual table.
An FTS table should be thought of as an index, not a table.
You should keep your original table, and put only the text column into an FTS table. (To avoid duplicate storage, you can use an external content table.)
I am creating an FTS4 external content table in SQLite like this:
CREATE TABLE t2(id INTEGER PRIMARY KEY, col_a, col_b, col_text);
CREATE VIRTUAL TABLE fts_table USING fts4(content="t2", col_text);
I'm using an external content table so that I don't need to store duplicate values of col_text in fts_table. I'm only indexing col_text because col_a and col_b don't need to be indexed.
However, when I do a query of fts_table like this
SELECT * FROM fts_table WHERE fts_table MATCH 'something';
I don't have access to col_a and col_b from the content table t2. How do return all these columns (col_a, col_b, col_text) from a single FTS query?
Update
I tried using the notindexed=column_name option as in
CREATE VIRTUAL TABLE fts_table USING fts4(content="t2", col_a, col_b, col_text, notindexed=col_a, notindexed=col_b);
This should work for some people, but I am using it in Android and the notindexed option isn't supported until SQLite 3.8, which Android doesn't support until Android version 5.x. And I need to support android 4.x. I am updating this question to include the Android tag.
FTS tables have an internal INTEGER PRIMARY KEY column called docid or rowid.
When inserting a row in the FTS table, set that column to the primary key of the row in the original table.
Then you can easily look up the corresponding row, either with a separate query, or with a join like this:
SELECT *
FROM t2
WHERE id IN (SELECT docid
FROM fts_table
WHERE col_text MATCH 'something')
I have an android application that contains 6 tables and pre populated ( contains data) each table contains at least 5000 records , and i want to support FTS3 , i understand that it's faster than regular SQLite tables . now should i convert these table schema to use FTS3
example :
CREATE VIRTUAL TABLE TABLE_1 USING fts3( col1, col2 ,....)
for each table of these 6 tables ? or i need to make a sperate table for each table and insert
the same records in the fts3 tables ???
FTS tables are not efficient for 'normal' queries, so it is likely that you still need your original tables.
FTS tables can be prepopulated just like normal tables.
If you decide to keep the original tables, you can save space by using contentless or external content FTS tables (see the documentation).
I have created an SQLite FTS3 table that I am using within the Android development platform (target is 2.2 and minVersion is 8). For example, I created the table as follows:
create virtual table person using fts3(first,last);
I know that when I insert data into this table, I long is returned, which is the row ID of the record inserted. How do I get the row ID from this table? If I perform:
select * from person
I get -1 for Cursor.getColumnColumnIndex("rowid");. Also, Cursor.getColumnNames() only shows the two columns ('first' and 'last') and not the 'rowid'. Any suggestikns on how to solve this problem?
Try using:
select rowid,* from person
Rowid is a hidden field and is not included in "*".