How to rawQuery in multiple columns in Sqflite - flutter

I created an onChanged function for a TextFormField to perform a query in multiple columns of a table. I tried to use OR in the WHERE clause, but it does not seem to work since it only returns queries from the first condition (columnOne), and not when I search for items from columnTwo or columnThree. Is there any other way I can achieve this?
onChanged: (String? databaseQuery) async {
Database db = await DatabaseHelper.instance.database;
List<Map> result = await db.rawQuery('SELECT * FROM table WHERE columnOne LIKE ? OR columnTwo LIKE ? OR columnThree LIKE ?', ['%$databaseQuery%']);
_map = result;
setState(() {});
}
Note: What I am trying to accomplish is like a Full Text Search, but I want to do it via rawQuery or query only instead of having to enable FTS. Thanks!

for each ? in the raw Query, you need also a argument
List<Map> result = await db.rawQuery('SELECT * FROM table WHERE columnOne LIKE ? OR columnTwo LIKE ? OR columnThree LIKE ?', ['%$databaseQuery%', '%$databaseQuery%', '%$databaseQuery%']);

Related

multiple arguments in sqflite flutter

I want to search database based on the keyword. if it title or content contains the keyword then return the data. but it send backs nothing.
static Future<List<Note>> searchDocuments(String? keyword) async {
final database = await DatabaseHelper.database();
List<Map<String, dynamic>> allDocuments = await database.rawQuery(
'SELECT * FROM docs WHERE title=? and content=?',
['$keyword%', '$keyword%']);
checked - doesn't work.
This works.
await database.rawQuery(
'SELECT * FROM docs WHERE title LIKE ? OR content LIKE ?',
['%$keyword%', '%$keyword%']);
await database.rawQuery(
'SELECT * FROM docs WHERE title="$keyword" AND content="$keyword"');

DocumentID search in Firestore with a List

Can i search a Firestore DocumentID with a List<String>?
I am trying to search through my collection with some selection of documentID in a List. The List will consist of few String. Can I search through the Firestore collection using this?
This is the List:
List<String> _selectedBusStop = List<String>();
This is the code I used in finding the DocumentID based on the list that is in here.
Future <void> saveRoute(_selectedBusStop) async{
Firestore.instance.collection('markers').where('BusstopName', isEqualTo: _selectedBusStop)
.snapshots().listen((location) {
if(location.documents.isNotEmpty){
for (int i = 0; i < location.documents.length; i++){
initRoute(location.documents[i].data, location.documents[i]);
}
}
});
setState(() {
});
}
I am using where and isEqualTo or is this approach wrong? Any idea how to make it work for this part? Thank you in advance for your help.
Update:
This is how my Firestore looks like:
The List have some of the BusstopName but not all of it. I do not want to retrieve all the data from the Firestore just the one that is in the List. Sorry for causing so many misunderstanding.
Use the whereIn operator, like this:
Future <void> saveRoute(_selectedBusStop) async{
Firestore.instance.collection('markers').where('BusstopName', whereIn: _selectedBusStop)
.snapshots().listen((location) {
if(location.documents.isNotEmpty){
for (int i = 0; i < location.documents.length; i++){
initRoute(location.documents[i].data, location.documents[i]);
}
}
});
setState(() {
});
}
Assuming your documents have a unique id stored in the field BusstopName and also the documents actual id matches the content of this field, you have 2 possibilities.
(1) .where query
query data with collection("markers").where("BusstopName", "=", "yourBuststopId").
this returns a querySnapshot Object, on which you can call .size to check if there were any documents with that Id found (could be more than 1 if you have an inconsistent database).
(2) .doc query
query data with collection("markers").doc("yourBuststopId")
this returns a documentSnapshot Object, on which you can call .exist to check if the document actually exsists.
In both cases you need to do 1 query per Id, because Firestore queries only support equality and range operations. See this similar SO question. I would suggest to do the queries asynchronously, otherwise the time to execute will increase with the size of the array.
If you are concerned about costs, you only get billed for the results that actually return documents that exist.
you might also try this:
FirebaseFirestore.instance
.collection('markers')
.where('BusstopName', arrayContainsAny: ['Utar Bus Stop', 'Garden Bus Stop'])
.get()
.then(...);
Taken from the examples documentation

How to combine 2 or more Sqflite queries with logical operators?

Im currently trying to combine the results of 2 queries in flutter. These are the queries:
Future<List> filterExercises({
List<String> equipmentFilter,
List<String> muscleFilter,
int custom, //0 = false, 1 = true
int recent, //0 = false, 1 = true
String orderBy,
}) async {
Database db = await initDatabase();
final muscleRes = await db.query(
'exercises',
where: "targetMuscle IN (${('?' * (muscleFilter.length)).split('').join(', ')})",
whereArgs: muscleFilter,
);
final equipmentRes = await db.query(
'exercises',
where: "equipment IN (${('?' * (equipmentFilter.length)).split('').join(', ')})",
whereArgs: equipmentFilter,
);
return finalResult; //need to combine the results with a logical AND somehow
}
I know there's the option the use a rawQuery with logical OR / AND, but that doesn't work for my case.
It should be possible for the user to select different attributes and thus filter the list. Im looking for a way to pass arguments to this function and query my table accordingly to the passed arguments but I already fail when merging the first two queries.
How to add a logical AND to these two queries?
And furthermore: How to add even more attributes with a logical AND and order the final result?
I managed to find a way to the first question:
List<String> muscleFilter = ['Chest', 'Biceps'];
List<String> equipmentFilter = ['Machine', 'Cable'];
return db.rawQuery('''
select * from exercises
where targetMuscle in (${('?' * (muscleFilter.length)).split('').join(', ')})
and equipment in (${('?' * (equipmentFilter.length)).split('').join(', ')})
''',
muscleFilter + equipmentFilter
);

Where in clause in Flutter sqflite

I'm trying to use where in clasue but i get this error:
Invalid argument [1, 2, 3] with type List Only num, String and
Uint8List are supported.
My code:
Database db = await instance.database;
List<Map> maps = await db.query('table',
where: 'categoryID in (?)', whereArgs: [ [1,2,3]]);
From this document
Particulary, lists (expect for blob content) are not supported. A
common mistake is to expect to use IN (?) and give a list of values.
This does not work. Instead you should list each argument one by one:
var list = await db.rawQuery('SELECT * FROM my_table WHERE name IN (?, ?, ?)', ['cat', 'dog', 'fish']);
But my categories can change any moment so I cant list each argument one by one.
While I understand that it could sound painful, that is unfortunately the way SQLite works and sqflite does not do any SQL parsing.
You could try the following solution that I personnaly use to build the proper number of ?.
List.filled(inArgsCount, '?').join(',')
For example:
var inArgs = ['cat', 'dog', 'fish'];
var list = await db.query('my_table',
where: 'name IN (${List.filled(inArgs.length, '?').join(',')})',
whereArgs: inArgs);

Multiple arguments in sqllite in flutter

I would like to know how to pass multiple arguments to a raw query in sqllite.
My code is below
query() async {
// get a reference to the database
Database db = await DatabaseHelper.instance.database;
// raw query
List<Map> result = await db.rawQuery('SELECT * FROM my_table WHERE name=?', ['Peter']);
// print the results
result.forEach((row) => print(row));
}
In the above code i am passing one argument 'Peter' but what if I want to pass multiple arguments, for example:
List<Map> result = await db.rawQuery('SELECT * FROM my_table WHERE name=? and last_name=? and year=?', ['Peter'], ['Smith'],[2019]);
If I do the code above, I get error "Too many positional arguments: 2 expected, but 4 found." can someone show me how to pass multiple arguments to a query in sqllite flutter?
I'm assuming you're using sqflite.
You need to put all your arguments into one list and not multiple.
The code below should work like this:
List<Map> result = await db.rawQuery(
'SELECT * FROM my_table WHERE name=? and last_name=? and year=?',
['Peter', 'Smith', 2019]
);
For more examples how to use raw queries see their examples on their pub.dev page.
Or if you want to use the query function you can do it like this:
String strVal = 'str';
int intVal = 0;
String likeVal = 'str';
final List<Map<String, dynamic>> maps = await db.query('my_table',
where: "col1 LIKE ? and col2 = ? and col3 = ?",
whereArgs: ['$likeVal%', strVal, intVal],
orderBy: 'id',
limit: 10);