how to query list of list in dart? - flutter

I got data from DB.
final List<SubCategoryModel> model;
my model class looks like this:
class SubCategoryModel{
final String categoryName;
final String subCategoryName;
final List<String> searchCategory;
}
Users can search categoryName or subCategoryName or any other common name. I stored common search names inside searchCategory. searchCategory is an array.
I don't understand query searchCategory in DB. Currently, I used this:
final result =
model.where((a) => a.subCategoryName.toLowerCase().contains(query)
|| a.categoryName.toLowerCase().contains(query));
Widget
ListView(
children: result
.map<InkWell>((a) => InkWell(...
Example:
CategoryName = Home
SubCategoryName = Kitchen
searchCategory = [Home,Service,Varanda,Bath Room]
Need to query from above three field

create a method for checking SearchCategory list
bool checkList(SubCategoryModel cat,String q){
for(int i = 0; i < cat. searchCategory.length;i++){
if(cat. searchCategory[i].toLowerCase().contains(q))
return true;
}
return false;
}
change query like this
final result = model.where((a) =>
a.subCategoryName.toLowerCase().contains(query) ||
a.categoryName.toLowerCase().contains(query) || checkList(a,query));

Related

Dart: CloudFirestore: Firebase -> How to pass firestore query operator as variable Query<T>.where(key, operator, value)

Firestore with Dart requires query operators to be passed as objects.
Docs: https://firebase.google.com/docs/firestore/query-data/queries
Ex Dart:
.where("key", isEqualTo: value)
Ex Go:
.where("key", "==", value).
In the case of go, passing a string "==" as the query operator is pretty straight forward.
For dart, i am trying to figure out how to store isEqualTo: as a variable, to then pass into the function.
Ok here is my code. Any help is really appreciated thank you!
Here is the DataModel
class FirestoreQueryModel extends Equatable {
//Variables
final String property;
final FirestoreOperatorEnum operator;
// This is the value where i want to store the list of operators
final dynamic value;
}
Here is the current repository
class CustomerRepository{
late Query golbalQuery
Stream <List<CustomerModel>> dynmamicCollectonStream(List<FirestoreQueryModel> queryList,) { //If query list is null, do not apply where clause
if (queryList.isEmpty) { return collectionRef().snapshots().map((doc) {var returnedList = doc.docs; var mappedList = returnedList.map((doc) => CustomerModel.fromDocument(doc)).toList();
return mappedList;
});
} else {var count = queryList.length; CollectionReference cRef = collectionRef();
for (var i = 0; i < count; i++) { golbalQuery = cRef.where(queryList[i].property, isEqualTo: queryList[i].value); }
var list = golbalQuery.snapshots().map((doc) { var returnedList = doc.docs; var mappedList = returnedList.map((doc) =\> CustomerModel.fromDocument(doc)).toList(); return mappedList; }); return list; } }}
In the for loop, where we convert the data model to a where clause I currently have hardcoded isEqualTo:
The goal is to convert
for (var i = 0; i < count; i++) { golbalQuery = cRef.where(queryList[i].property, isEqualTo: queryList[i].value); }
to
for (var i = 0; i < count; i++) { golbalQuery = cRef.where(queryList[i].property, qyeryList[i].operator, queryList[i].value); }

in return only show Instance of 'User' User is a class

I want this code to convert a csv file to a list, and then convert it to json, for the firebase database, instead of list this code return array it shows an instance of class, like this :
[Instance of 'User', Instance of 'User', Instance of 'User']
void main() {
var users= "username, email, phone \n ctavia,octavia#gmail.com, 099-83-44 \n lark, clark#gmail.com, 054-83-23 \n aven, raven#gmail.com, 784-44-98";
var data = csvToUsersList(users);
print(data);
}
class User {
String username;
String email;
String phone;
User(this.username, this.email, this.phone);
}
List<User> csvToUsersList(String data) {
List<User> users = [];
List<String> userin= data.split("\n");
for (int i = 1; i < userin.length; i++) {
List<String> user = userin[i].split(",");
users.add(User(user[0], user[1], user[2]));
}
return users;
}
That seems correct. If you print something like data.first.username, you should get the name of the first User.
Instance of User just means, that this is an Object of Type User.

How to get aggregated data in moor_flutter?

Let's say I have 2 simple tables Users and Orders:
Users has columns Id
Orders has columns Id and UserId
How do I get all orders of a user easily using moor_flutter and return it as a stream of the following model?
class UserModel {
final String id;
final List<OrderModel> orderModels;
UserModel(this.id, this.orders);
}
class OrderModel {
final String id;
OrderModel(this.id);
}
This is the official documentation but it is not covering this use case.
Equivalent call with EFCore and C# would be:
public async Task<IEnumerable<UserModel>> GetUserOrders(String userId)
{
return await _db.Users
.Include(user => user.Orders)
.Where(user => user.Id == userId)
.Select(user => new UserModel
{
Id = user.Id,
OrderModels = user.Orders.Select(order => new OrderModel
{
Id = null,
}).ToList()
})
.ToListAsync();
}
I faced the same problem recently. I was confused to use Joins as per the given example in documentation.
What I have done is:
The created class (in database file only. see below example) has two objects which you want to join(combine). I wrote the query in a class of database.
You will get better understanding with example:
#UseMoor(
tables: [OfflineProductMasters, OfflineProductWiseStocks],
)
class MyDatabase extends _$MyDatabase {
// we tell the database where to store the data with this constructor
MyDatabase() : super(_openConnection());
// you should bump this number whenever you change or add a table definition. Migrations
// are covered later in this readme.
#override
int get schemaVersion => 1;
Future<List<ProductWithStock>> getProductWiseStock(String searchString, int mappingOfflineSalesTypeId) async {
try {
final rows = await (select(offlineProductMasters).join([innerJoin(offlineProductWiseStocks, offlineProductMasters.itemId.equalsExp(offlineProductWiseStocks.itemId))])
..where(offlineProductWiseStocks.salesTypeId.equals(mappingOfflineSalesTypeId) & offlineProductMasters.productName.like('$searchString%'))
..limit(50)
).get();
return rows.map((row) {
return ProductWithStock(
row.readTable(offlineProductMasters),
row.readTableOrNull(offlineProductWiseStocks),
);
}).toList();
}catch(exception){
print(exception);
return Future.value([]);
}
}
}
class ProductWithStock {
final OfflineProductMaster offlineProductMaster;
final OfflineProductWiseStock? productWithStock;
ProductWithStock(this.offlineProductMaster, this.productWithStock);
}
Now you got the structure that how you can use this type of query. Hope you will write your query in this way.
I don't know whether you have solved it or not. If solved then please post the answer so others can get help.
Thank you.
This feels like a hacky workaround but what I ended up doing is that I created 2 classes called HabitWithLogs and HabitModel. I put my query result into HabitWithLogs instances and then group them into HabitModel instances.
Data classes:
class HabitWithLog {
final Habit habit;
final HabitLog? habitLog;
HabitWithLog({required this.habit, required this.habitLog}) : assert(habitLog == null || habitLog.habitId == habit.id);
}
class HabitModel {
final Habit habit;
final List<HabitLog> habitLogs;
HabitModel({required this.habit, required this.habitLogs});
}
Dao method:
Future<List<HabitModel>> getAllHabits() async {
// Get habits and order
final query0 = (_db.select(_db.habits)..orderBy([(t) => OrderingTerm(expression: t.order, mode: OrderingMode.asc)]));
// Join with habit logs
final query1 = query0.join([
leftOuterJoin(_db.habitLogs, _db.habitLogs.habitId.equalsExp(_db.habits.id)),
]);
// Naive way that return the same habit multiple times
final hwlList = query1.map((rows) => HabitWithLog(
habit: rows.readTable(_db.habits),
habitLog: rows.readTableOrNull(_db.habitLogs),
));
// Group hwlList by habits
final groups = (await hwlList.get()).groupListsBy((hwl) => hwl.habit);
// Map grouping
return groups.entries
.map((group) => HabitModel(
habit: group.key,
habitLogs: (group.value[0].habitLog == null) ? List<HabitLog>.empty() : group.value.map((hwl) => hwl.habitLog!).toList(),
))
.toList();
}
Mapping the stream feels terrible and should not be the only way to achieve this.

Comparing list with another list items and returning it if it has similar items

class Object1 {
final String id;
List<Object1list> lists = [];
Object1({this.id, this.lists});
class Object1list {
final String id;
final String item;
Object1list({this.id});
}
List<String> searchlist = ['object1','object2','object3'];
What i want to do is I want to search "object1list" items for "any" matches with "searchlist" items and
return it as contain function but I don't know how, something like:
return ???.contains(???)
Can somebody help me?
The below function will help you to get matched items:
bool doSearch(List<String> searchlist, List<String> lists) {
List<String> matched = [];
for (String s in searchlist) {
if (lists.contains(s)) {
matched.add(s);
}
//else {
// return false; // Uncomment these lines if you want "lists" to contain all searched items
//}
}
return matched.length > 0; // This for 0 or more items matched
}
Other ways:
import 'package:enumerable/enumerable.dart';
void main() {
final result1 = searchlist.isNotEmpty
? searchlist.distinct().length == searchlist.length
: false;
print(result1);
// OR
final result2 = searchlist.isNotEmpty
? searchlist.toSet().length == searchlist.length
: false;
print(result2);
}
List<String> searchlist = ['object1', 'object2', 'object3', 'object2'];

How to convert List<Object> flutter

i'm new in flutter and need to help:
I have already got
final List<Genres> genres = [{1,"comedy"}, {2,"drama"},{3,"horror"}]
from api.
class Genres {
final int id;
final String value;
Genres({this.id,this.value});
}
In another method I get genres.id.(2) How can I convert it to genres.value ("drama")?
Getting a Genre from an id is inconvenient when your data structure is a List. You have no choice but to iterate over the list and compare the id value to the id of each element in the list:
final id = 2;
final genre = genres.firstWhere((g) => g.id == id, orElse: () => null);
The problem with this code is that it's slow and there could be multiple matches (where the duplicates after the first found would be ignored).
A better approach would be to convert your list to a Map when you first create it. Afterwards, you can simply use an indexer to get a Genre for an ID quickly and safely.
final genresMap = Map.fromIterable(genres, (item) => item.id, (item) => item);
// later...
final id = 2;
final genre = genresMap[id];
This way, there is guaranteed to not be any duplicates, and if an ID doesn't exist then the indexer will simply return null.
you could iterate over the json result of the api and map them to the Gener class like so,
void fn(id) {
final gener = geners.firstWhere((gener) => gener['id'] == id);
// now you have access to your gener
}
You can find the item inside the List<Genres> like this
Genres element = list.firstWhere((element) => element.id == 2); // 2 being the id you give in the question as an exaple. You should make it dynamic
print(element.value);